XSL 2.0:根据预定义的属性调用模板

时间:2016-05-04 14:08:13

标签: templates xslt attributes xslt-2.0

我尝试在XSLT 2.0中进行转换

<data>
  <attributes>
    <attribute code="Name" datatyp="String" class="A"></attribute>
    <attribute code="Age" datatyp="Integer" class="A"></attribute>
    <attribute code="sex" datatyp="String" class="A"></attribute>
    <attribute code="height" datatyp="Integer" class="B"></attribute>
  </attributes>
  <personal>
    <name>Klaus</name>
    <Age>16</Age>
    <sex>male</sex>
    <height>180</height>
  </personal>
  <personal>
    <height>165</height>
  </personal>
</data>

为Person 1

做类似的事情
<personal>
  <class>
    <classtype>A</classtype>
    <name>Klaus</name>
    <Age>16</Age>
    <sex>male</sex>
  </class>
  <class>
    <classtype>B</classtype>
    <height>180</height>
  </class> 
</personal>
<personal>
  <class>
    <classtype>B</classtype>
    <height>165</height>
  </class> 
</personal>

哪个属性出现在哪个类的依赖项在Input XML的开头定义。我需要为每个人调用A类和B类的模板一次,这就是为什么我的尝试不能正常工作。

<xsl:for-each select="...personal/*">   
  <xsl:variable name="code"><xsl:value-of select="name()"></xsl:value-of> </xsl:variable>
  <xsl:if test="//attribute[@code=$code]/@class='A'">
    <!-- call template A -->

我需要一些帮助来解决根据给定参数调用正确模板的问题。

2 个答案:

答案 0 :(得分:1)

这对你有用吗?

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="attr-by-code" match="attribute" use="@code" />

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="personal">
    <xsl:copy>
        <xsl:for-each-group select="*" group-by="key('attr-by-code', name())/@class">
            <class> 
                <classtype>
                    <xsl:value-of select="current-grouping-key()" />
                </classtype>
                <xsl:apply-templates select="current-group()" />
            </class>
        </xsl:for-each-group>   
    </xsl:copy>
</xsl:template>

<xsl:template match="attributes"/>

</xsl:stylesheet>

答案 1 :(得分:0)

更简单,缩短两倍以上,保留顺序并且非常正确

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <xsl:key name="kAttrByCode" match="attribute" use="@code"/>

  <xsl:template match="personal">
    <xsl:copy>
      <xsl:for-each-group select="*[key('kAttrByCode', name())]" 
                          group-adjacent="key('kAttrByCode', name())/@class">
        <class>
          <classtype><xsl:sequence select="current-grouping-key()"/></classtype>
          <xsl:sequence select="current-group()"/>
        </class>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

对提供的XML文档应用此转换时(请注意code="Name"已更正为code="name" - 否则必须使用大小写转换函数来实现不区分大小写):

<data>
    <attributes>
        <attribute code="name" datatyp="String" class="A"></attribute>
        <attribute code="Age" datatyp="Integer" class="A"></attribute>
        <attribute code="sex" datatyp="String" class="A"></attribute>
        <attribute code="height" datatyp="Integer" class="B"></attribute>
    </attributes>
    <personal>
        <name>Klaus</name>
        <Age>16</Age>
        <sex>male</sex>
        <height>180</height>
    </personal>
    <personal>
        <height>165</height>
    </personal>
</data>

产生了想要的正确结果

<personal>
   <class>
      <classtype>A</classtype>
      <name>Klaus</name>
      <Age>16</Age>
      <sex>male</sex>
   </class>
   <class>
      <classtype>B</classtype>
      <height>180</height>
   </class>
</personal>
<personal>
   <class>
      <classtype>B</classtype>
      <height>165</height>
   </class>
</personal>

<强>解释

  1. <xsl:for-each-group>指令与属性group-adjacent

  2. 一起使用
  3. 使用标准XSLT函数current-group()current-grouping-key()