使用XSLT在节点计数时使用条件转换XML

时间:2012-03-18 13:37:55

标签: xml xslt

我正在尝试从XML文件中删除节点。我只需要为每个XML使用一个XSLT,我需要根据文档元素的子项数在XSLT中做出决策。

<root>
  <branch>
    <foo>bar</foo>
  </branch>
<root>

应该变成

  <branch>
  </branch>

但是

<root>
  <branch>
    <foo>bar</foo>
  </branch>
  <branch>
    <foo>baz</foo>
<root>

<root>
  <branch>
  </branch>
  <branch>
  </branch>
<root>

也就是说,如果根元素的(仅)子元素在应用XSLT后可以充当结果XML的新文档根,则应该删除它。每次出现时都必须删除<foo>个节点。

有没有办法用单个XSL执行此操作?

2 个答案:

答案 0 :(得分:2)

尝试

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

<xsl:template match="root[*[2]]">
  <xsl:copy>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

<xsl:template match="root[* and not(*[2])]">
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="branch/foo"/>

答案 1 :(得分:2)

更简单,更短,更通用(没有元素名称硬编码)解决方案

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

 <xsl:template match="/*[not(*[2])]">
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="/*/*/node()"/>
</xsl:stylesheet>

将此转换应用于第一个提供的XML文档(更正为格式良好):

<root>
    <branch>
        <foo>bar</foo>
    </branch>
</root>

产生了想要的正确结果

<branch></branch>

对第二个提供的XML文档应用相同的转换(再次需要针对格式良好进行更正):

<root>
    <branch>
        <foo>bar</foo>
    </branch>
    <branch>
        <foo>baz</foo>
    </branch>
</root>

再次生成想要的正确输出

<root>
    <branch></branch>
    <branch></branch>
</root>

<强>解释

  1. identity rule “按原样”复制每个节点。

  2. 有两个模板覆盖特定节点的身份模板,并以不同方式处理这些节点。

  3. 第一个覆盖模板匹配没有第二个元素子元素的顶部元素。它不会复制元素本身,而是处理其子元素。

  4. 第二个覆盖模板匹配顶级元素的子元素。此模板没有正文,这意味着所有此类匹配的元素都会被忽略,并且不会包含在输出中(换句话说 - “已删除”)

  5. 请注意

    此转换可应用于任何 XML文档,无论其中的元素名称如何,仍然可以生成所需的正确结果。

    例如,在应用于此XML文档时:

    <t>
        <b>
            <f>brrr</f>
        </b>
        <b>
            <f>bzzz</f>
        </b>
    </t>
    

    产生了想要的正确结果

    <t>
        <b></b>
        <b></b>
    </t>
    

    将此与当前接受的答案产生的结果进行对比

    <t>
        <b>
            <f>brrr</f>
        </b>
        <b>
            <f>bzzz</f>
        </b>
    </t>