2013-06-07 1 views
2

мне нужно использовать XSLT для отображения значений из этого формата:Использование XSLT для разделения коллекции объектов и перераспределения?

<Package> 
<WorkflowProcesses> 
    <WorkflowProcess>    
     <Activities>     
      <Activity Name="First Activity" Id="123">      
      </Activity>  
      <Activity Name="Second Activity" Id="456">      
      </Activity> 
      <Activity Name="Third Activity" Id="789">      
      </Activity> 
     </Activities> 
     <Transitions> 
      <Transition To="789" From="456" Id="ABC">     
      </Transition> 
      <Transition To="456" From="123" Id="XYZ">      
      </Transition>    
     </Transitions> 
    </WorkflowProcess> 
</WorkflowProcesses> 
</Package> 

в этот формат:

<variable type="State"> 
    <stateId type="Integer">123</stateId> 
    <stateName type="String">First Activity</stateName> 
    <previousStatesId type="String[]">  
    </previousStatesId> 
    <nextStatesId type="String[]"> 
     <item>456</item> 
    </nextStatesId> 
</variable>   

<variable type="State"> 
    <stateId type="Integer">456</stateId> 
    <stateName type="String">Second Activity</stateName> 
    <previousStatesId type="String[]"> 
    <item>123</item> 
     </previousStatesId> 
    <nextStatesId type="String[]"> 
     <item>789</item> 
    </nextStatesId> 
</variable>  

<variable type="State"> 
    <stateId type="Integer">789</stateId> 
    <stateName type="String">Third Activity</stateName> 
    <previousStatesId type="String[]"> 
    <item>456</item> 
    </previousStatesId> 
    <nextStatesId type="String[]"> 
    </nextStatesId> 
</variable> 

Та часть, я борюсь с, чтобы получить значения из «Transitions 'и назначьте их правильной области (' nextStatesId 'и' previousStatesId '); все остальное работает как ожидалось.

До сих пор, я успешно картографирования элементы деятельности с использованием этого:

<xsl:template match="Activities"> 
<xsl:apply-templates/> 
</xsl:template> 

<xsl:template match="Activity [@Name]"> 
<variable type="State"> 
    <stateId type="Integer"><xsl:value-of select="@Id"/></stateId> 
    <stateName type="String"><xsl:value-of select="@Name"/></stateName> 
    </variable> 
</xsl:template> 
</xsl:stylesheet> 

я могу использовать это, чтобы определить все элементы переходной, то я собирался сравнивать идентификатор перехода с текущую активность, но она не работает в шаблоне выше. Я предполагаю, что это потому, что шаблон не имеет видимость всего файла XML и поэтому не понимает отображение

<xsl:for-each select="Package/WorkflowProcesses/WorkflowProcess/Transitions/Transition">  
     <p>...do some stuff...</p>   
    </xsl:for-each> 

Обычно, если я кодирования, я бы просто засунуть их в два списка и затем искать их. То, что я планировал сделать здесь, состояло в том, чтобы просто перебрать все переходы из каждого действия с помощью простого оператора «if» для предыдущего/следующего состояния id ... но это, похоже, терпит неудачу.

Кто-нибудь знает о другом методе достижения этого?

ответ

1

Если поместить for-each внутри шаблона он будет искать для ребенкаPackage/... в деятельности. Но их нет.

Что вы пытаетесь сделать здесь, это получить доступ к корневому узлу. Поэтому поставьте косую черту «/» перед Package.

<xsl:for-each select="/Package/WorkflowProcesses/WorkflowProcess/Transitions/Transition">  
     <p>...do some stuff...</p>   
</xsl:for-each> 

Однако, я бы не рекомендовал использовать for-each здесь. applay-templates будет лучше. Try:

<xsl:template match="Activity[@Name]"> 
    <variable type="State"> 
     <stateId type="Integer"> 
      <xsl:value-of select="@Id"/> 
     </stateId> 
     <stateName type="String"> 
      <xsl:value-of select="@Name"/> 
     </stateName> 
     <previousStatesId type="String[]"> 
      <xsl:apply-templates select="//Transition[@To =current()/@Id]" 
           mode="from" /> 
     </previousStatesId> 
     <nextStatesId type="String[]"> 
      <xsl:apply-templates select="//Transition[@From =current()/@Id]" 
           mode="to" /> 
     </nextStatesId> 

    </variable> 
</xsl:template> 

<xsl:template match="Transition" mode="from"> 
    <item> 
     <xsl:value-of select="@From"/> 
    </item> 
</xsl:template> 
<xsl:template match="Transition" mode="to"> 
    <item> 
     <xsl:value-of select="@To"/> 
    </item> 
</xsl:template> 
+0

также отличное решение - благодаря – user1711233

+0

Совершенная: также работает для нескольких переходов в/из того же узла, который еще лучше. – user1711233

1

Это преобразование, кажется, делать то, что вы спрашиваете.

Ваш «в этот формат» не имеет правильной формы, поскольку он не имеет корневого элемента, поэтому я добавил элемент фиктивного элемента <root>.

Преобразование использует ключи для доступа к элементам Transition по их атрибутам.

Интересно, если вы действительно необходимо пространство и содержимое новой строки в вашем случае пустой previousStatesId и nextStatesId выходных элементов? Это преобразование создает самозакрывающиеся пустые элементы. Это изменение не составит труда, если вам потребуется строгая точность.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 

    <xsl:key name="transition-from" match="Transition" use="@From"/> 
    <xsl:key name="transition-to" match="Transition" use="@To"/> 

    <xsl:template match="/"> 
    <root> 
     <xsl:apply-templates select="Package/WorkflowProcesses/WorkflowProcess/Activities/Activity"/> 
    </root> 
    </xsl:template> 

    <xsl:template match="Activity"> 
    <xsl:variable name="from-here" select="key('transition-from', @Id)"/> 
    <xsl:variable name="to-here" select="key('transition-to', @Id)"/> 
    <variable type="State"> 
     <stateId type="Integer"> 
     <xsl:value-of select="@Id"/> 
     </stateId> 
     <stateName type="String"> 
     <xsl:value-of select="@Name"/> 
     </stateName> 
     <previousStatesId type="String[]"> 
     <xsl:if test="$to-here"> 
      <item> 
      <xsl:value-of select="$to-here/@From"/> 
      </item> 
     </xsl:if> 
     </previousStatesId> 
     <nextStatesId type="String[]"> 
     <xsl:if test="$from-here"> 
      <item> 
      <xsl:value-of select="$from-here/@To"/> 
      </item> 
     </xsl:if> 
     </nextStatesId> 
    </variable> 
    </xsl:template> 

</xsl:stylesheet> 

выход

<root> 
    <variable type="State"> 
     <stateId type="Integer">123</stateId> 
     <stateName type="String">First Activity</stateName> 
     <previousStatesId type="String[]"/> 
     <nextStatesId type="String[]"> 
     <item>456</item> 
     </nextStatesId> 
    </variable> 
    <variable type="State"> 
     <stateId type="Integer">456</stateId> 
     <stateName type="String">Second Activity</stateName> 
     <previousStatesId type="String[]"> 
     <item>123</item> 
     </previousStatesId> 
     <nextStatesId type="String[]"> 
     <item>789</item> 
     </nextStatesId> 
    </variable> 
    <variable type="State"> 
     <stateId type="Integer">789</stateId> 
     <stateName type="String">Third Activity</stateName> 
     <previousStatesId type="String[]"> 
     <item>456</item> 
     </previousStatesId> 
     <nextStatesId type="String[]"/> 
    </variable> 
</root> 
+0

Отличный ответ, именно то, что я искал, и легко понять. – user1711233

+0

// Редактирование: на самом деле он не работает для нескольких переходов из/в одну и ту же активность, только в первую. Спасибо, в любом случае. Я понимаю, что я не уточнил это с вопросом, так что еще хороший ответ! :-) – user1711233

Смежные вопросы