为同一节点(XSLT)运行两个模板

时间:2015-06-29 11:34:12

标签: xml xslt

我有一些像下面这样的xml文件。它们包含所有不同的树结构,而某些元素具有属性。

<root>
  <element n="A">
    <element n="B">
      <attribute a="1"/>
      <attribute a="2"/>
    </element>
    <element n="C">
      <element n="D">
        <attribute a="3"/>
      </element>
    </element>
  </element>
</root>

我想使用XSLT转换这些文件以获得以下输出。我必须保留树结构,并创建一个包含其属性的所有元素的列表:

<root>
  <structure>
    <newElement n="A">
      <newElement n="B">
        <newAttribute a="1"/>
        <newAttribute a="2"/>
      </newElement>
      <newElement n="C">
        <newElement n="D">
          <newAttribute a="3"/>
        </newElement>
      </newElement>
    </newElement>
  </structure>
  <list>
    <listElement n="A"/>
    <listElement n="B">
      <listAttribute a="1"/>
      <listAttribute a="2"/>
    </listElement>
    <listElement n="C"/>
    <listElement n="D">
      <listAttribute a="3"/>
    </listElement>
  </list>
</root>

我尝试为一个节点“元素”运行两个不同的模板“e1”和“e2”,但它不起作用。似乎忽略了第一个模板。那么我需要改变什么?

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

<xsl:template match="/">
  <root>
    <structure>
      <xsl:apply-templates name="e1"/>
    </structure>
    <list>
      <xsl:apply-templates name="e2"/>
    </list>
  </root>
</xsl:template>

<xsl:template match="element" name="e1">
  <newElement>
    <xsl:attribute name="n">
      <xsl:value-of select="@n"/>
    </xsl:attribute>
    <xsl:apply-templates name="a1"/>
    <xsl:apply-templates name="e1"/>
  </newElement>
</xsl:template>

<xsl:template match="attribute" name="a1">
  <newAttribute>
    <xsl:attribute name="a">
      <xsl:value-of select="@a"/>
    </xsl:attribute>
  </newAttribute>
</xsl:template>

<xsl:template match="element" name="e2">
  <listElement>
    <xsl:attribute name="n">
      <xsl:value-of select="@n"/>
    </xsl:attribute>
    <xsl:apply-templates name="a2"/>
  </listElement>
  <xsl:apply-templates select="element"/>
</xsl:template>

<xsl:template match="attribute" name="a2">
  <listAttribute>
    <xsl:attribute name="a">
      <xsl:value-of select="@a"/>
    </xsl:attribute>
  </listAttribute>
</xsl:template>

</xsl:stylesheet>

1 个答案:

答案 0 :(得分:5)

name上使用xsl:apply-templates属性无效。我猜你的XSLT处理只是在这种情况下忽略了名称而只是简单的<xsl:apply-templates />

我认为您需要使用的是mode属性。当您使用mode属性时,它只会使用具有相同mode的匹配模板,从而允许您拥有两个匹配相同元素的模板。

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <root>
    <structure>
      <xsl:apply-templates mode="e1"/>
    </structure>
    <list>
      <xsl:apply-templates mode="e2"/>
    </list>
  </root>
</xsl:template>

<xsl:template match="element" mode="e1">
  <newElement n="{@n}">
    <xsl:apply-templates mode="e1"/>
  </newElement>
</xsl:template>

<xsl:template match="attribute" mode="e1">
  <newAttribute a="{@a}"/>
</xsl:template>

<xsl:template match="element" mode="e2">
  <listElement n="{@n}">
    <xsl:apply-templates select="attribute" mode="e2"/>
  </listElement>
  <xsl:apply-templates select="element" mode="e2"/>
</xsl:template>

<xsl:template match="attribute" mode="e2">
  <listAttribute a="{@a}"/>
</xsl:template>
</xsl:stylesheet>

注意使用&#34;属性值模板&#34;这里,为了简化XSLT。