【问题标题】:Transform nested xml items with xslt使用 xslt 转换嵌套的 xml 项
【发布时间】:2010-10-11 10:21:46
【问题描述】:

如何使用 xslt 转换嵌套的 XML 元素,同时保持结构?

假设我有一个这样的 XML 文档:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <node>
  </node>
  <node>
    <node>
      <node>
      </node>
    </node>
  </node>
</root>

我想得到这样的东西:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <element>
    </element>
    <element>
      <element>
        <element>
        </element>
      </element>
    </element>
</root>

我应该使用哪种 xslt?

谢谢!

【问题讨论】:

  • “什么样的”?这甚至意味着什么?
  • 第二个示例不是有效的 XML,因为有 2 个根元素。一个有效的 XML 文档中只能有一个根元素。
  • @Ignacio:我的意思是你能帮我写一个与示例 xmls 一起工作的 xslt 吗? @Oded:你说得对,我修正了。
  • 好问题,+1。请参阅我对使用 identity 规则和纯推送样式的经典、最“符合 XSLT 精神”的解决方案的回答。 :)

标签: xml xslt


【解决方案1】:

在 XSLT 中执行此操作的方法是这样的(使用 identity rule 和 push 样式)

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <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="node">
  <element>
    <xsl:apply-templates select="node()|@*"/>
  </element>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时

<root>
  <node>
  </node>
  <node>
    <node>
      <node>
      </node>
    </node>
  </node>
</root>

产生想要的正确结果

<root>
   <element/>
   <element>
      <element>
         <element/>
      </element>
   </element>
</root>

请注意

  1. 身份规则的使用及其仅针对特定元素的覆盖——这是最基本和最强大的 XSLT 设计模式。

  2. 如何通过上面的1.实现优雅而纯粹的“推式”改造

【讨论】:

  • 我知道这是一个较旧的答案,但我很好奇:为什么&lt;xsl:template match="node"&gt; 模板将node()|@* 指定为&lt;xsl:apply-templates&gt; 的选择器?据我所知,直接的&lt;xsl:apply-templates /&gt; 完成了同样的事情(因为身份模板已经指定了该选择器)。
  • @ABach:身份规则的强大之处在于无需修改即可使用它——在这种特殊情况下,没有属性,但明天有人可以更改 XML 文档的格式并添加一些属性。如果您遵守了确切的身份规则,您甚至不必更改单个字符 - 一切都会继续按预期工作。
  • 啊,我明白了 - 我不认为在该级别使用 &lt;xsl:apply-templates /&gt; 不会捕获子/孙/等中的属性。节点。谢谢,@Dimitre!
  • @Abach:不客气。您可以在此处阅读有关身份规则的更多信息:dpawson.co.uk/xsl/sect2/identity.html
【解决方案2】:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/root">
    <root>
      <xsl:apply-templates />
    </root>
  </xsl:template>
  <xsl:template match="node">
    <element>
      <xsl:apply-templates />
    </element>
  </xsl:template>
</xsl:stylesheet>

关键是apply-templates标签,递归处理标签内容。

【讨论】:

  • 好答案。您可能有兴趣了解 identity rule 设计模式——请参阅我的回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-22
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多