XSLT 2.0:覆盖具有孙子节点的节点

时间:2012-02-28 16:09:02

标签: xslt-2.0 xpath-2.0

我正在尝试找到一种方法来替换树中具有相同名称的节点。例如,使用以下输入:

<root>
    <foo>
        <a>1</a>
        <b>2</b>
        <c>3</c>
        <bar>
            <a>100</a>
            <c>5000</c>
        </bar>
    </foo>
</root>

我想生产这样的东西:

<root>
    <foo>
        <a>100</a>
        <b>2</b>
        <c>5000</c>
    </foo>
</root>

我需要能够替换任意数量的节点,并且我还想动态地找出列表,而不是拼出所有可能性,因为将来可能会发生变化。另一个要求是父节点的顺序必须保持不变。 (具体来说,我的最终输出将是一个CSV文件,因此列需要与标题对齐。)

这是我第一次尝试学习XSLT,我完全被这个问题困住了!任何帮助将不胜感激。我正在使用XSLT 2.0,BTW。

谢谢, 标记

1 个答案:

答案 0 :(得分:0)

我为那些不会缩进格式化代码的讨厌的SO错误道歉!

他们几个月都无法解决这个问题......

此转化

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match=
 "*[*]
       [every $leaf in .//*[not(*)]
      satisfies
        name($leaf) = preceding::*/name()
       ]
 "/>

 <xsl:template match=
  "*[not(*) and name() = following::*/name()]">

  <xsl:sequence select=
  "following::*[name() = name(current())][1]"/>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<root>
    <foo>
        <a>1</a>
        <b>2</b>
        <c>3</c>
        <bar>
            <a>100</a>
            <c>5000</c>
        </bar>
    </foo>
</root>

生成想要的正确结果

<root>
   <foo>
      <a>100</a>
      <b>2</b>
      <c>5000</c>
   </foo>
</root>