将XSLT重用于不同的元素(循环?)

时间:2014-10-16 10:12:05

标签: c# xml xslt xpath xslt-1.0

感谢上一篇文章我现在可以转换

<root>
<parent>
<Jack>value1</Jack>
<Jane>value2</Jane>
<spArchie>value3</spArchie>
<spKate>value4</spKate>
</parent>
</root>

<root>
<parent>
<Jack>value1</Jack>
<Jane>value2</Jane>
<childlist>
<value name="spArchie">value3</value>
<value name="spKate">value4</value>
</childlist>
</parent>
</root>

使用以下XSLT                                    
    

<xsl:template match="childlist[normalize-space(spArchie) or normalize-space(spKate)]">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()[not(self::spArchie | self::spKate)]"/>
    <childlist>
      <xsl:apply-templates select="spArchie | spKate" mode="wrap"/>
    </childlist>
  </xsl:copy>
</xsl:template>

<xsl:template match="childlist[not('' = (../spArchie|../spKate))]">
    <xsl:copy>
        <xsl:apply-templates select="spArchie[normalize-space()] | spKate[normalize-space()]" mode="wrap"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="spArchie[normalize-space()] | spKate[normalize-space()]" mode="wrap">
  <value name="{local-name()}">
    <xsl:apply-templates/>
  </value>
</xsl:template>

到目前为止一直很好,但是在xml文档中我还有许多与父级相同级别的其他节点,我想要应用相同的功能但具有不同的元素名称。我想改变

 <teacher>
 <Rachel>value1</Rachel>
 <spChristine>value2</spChristine>
 <spPeter>value3</spPeter>
 <Daisy>value4</Daisy>
 </teacher>

<teacher>
<Rachel>value1</Rachel>
<Daisy>value4</Daisy>
<studentlist>
<value name="Christine">value2</value>
<value name="Peter">value3</value>
</studentlist>
</teacher>

我显然可以复制已经使用不同值创建的xslt,但是这个想法会让我的皮肤爬行(如果有人看到它就会面临红色)。有没有办法在循环中执行我的xslt传递我想要搜索和移动的节点的参数。到目前为止我的想法是

  • 收集与父
  • 相同级别的所有节点
  • 查找前缀为sp。
  • 的父级的所有子节点
  • 将这些参数传递给我已经拥有的xslt。

我正在寻找实施此解决方案的反馈和指示。绩效是一个关键问题。

非常感谢

1 个答案:

答案 0 :(得分:1)

我认为您的原始样式表可以更简单,也更通用:

XSLT 1.0

<xsl:stylesheet version="1.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="*"/>

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

<xsl:template match="/root/*">
    <xsl:copy>
        <xsl:apply-templates select="*[not (starts-with(local-name(), 'sp'))]"/>
        <childlist>
            <xsl:apply-templates select="*[starts-with(local-name(), 'sp')]" mode="sp"/>
        </childlist>
    </xsl:copy>
</xsl:template>

<xsl:template match="*" mode="sp">
    <value name="{local-name()}">
        <xsl:apply-templates/>
    </value>
</xsl:template>

</xsl:stylesheet>

但是,您无法将此直接应用于新的示例输入,因为:

  1. 结构不相同(没有父root元素);
  2. 名称studentlist必须来自某个地方。

  3. 编辑:

      

    然而在xml文档中我还有很多其他节点   与我想要将相同功能应用于

    的父级相同的级别

    我错过了这一部分。如果它们在同一文档中并且在同一级别上,例如

    <强> XML

    <root>
        <parent>
            <Jack>value1</Jack>
            <Jane>value2</Jane>
            <spArchie>value3</spArchie>
            <spKate>value4</spKate>
        </parent>
        <teacher>
            <Rachel>value1</Rachel>
            <spChristine>value2</spChristine>
            <spPeter>value3</spPeter>
            <Daisy>value4</Daisy>
        </teacher>
    </root>
    

    然后上面的样式表将返回:

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
       <parent>
          <Jack>value1</Jack>
          <Jane>value2</Jane>
          <childlist>
             <value name="spArchie">value3</value>
             <value name="spKate">value4</value>
          </childlist>
       </parent>
       <teacher>
          <Rachel>value1</Rachel>
          <Daisy>value4</Daisy>
          <childlist>
             <value name="spChristine">value2</value>
             <value name="spPeter">value3</value>
          </childlist>
       </teacher>
    </root>