使用XSLT拆分对象集合并重新分配?

时间:2013-06-07 15:57:33

标签: 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>  

我正在努力的部分是从“转换”部分获取值并将它们分配到正确的区域('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>

我可以用它来识别所有的Transition项,然后我将比较Transition的id和当前的Activity,但它在上面的模板中不起作用。我假设这是因为模板没有整个XML文件的可见性,因此无法理解映射

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

通常,如果我正在编码,我只需将它们推入两个列表然后搜索它们。我打算在这里做的只是循环遍历每个Activity中的所有转换,并使用前一个/下一个状态id的简单'if'语句......但这似乎失败了。

有没有人知道另一种方法来实现这个目标?

2 个答案:

答案 0 :(得分:1)

如果您将for-each放在模板中,它将在活动中搜索孩子 Package/...。但没有。

您在此处尝试执行的操作是访问根节点。因此,在/之前加上斜杠“Package”。

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

但是,我不建议在这里使用for-eachapplay-templates会更合适。 尝试:

<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>

答案 1 :(得分:1)

这种转变似乎符合你的要求。

你的“这种格式”格式不正确,因为它没有根元素,所以我添加了一个虚拟<root>元素。

转换使用键来按属性访问Transition元素。

我想知道你真的是否需要空格previousStatesIdnextStatesId输出元素中的空格和换行内容?此变换生成自闭合空元素。如果您需要严格的准确性,这种改变并不难。

<?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>