2012-03-18 32 views
3

我试图从XML文件中删除节点。对每个XML只使用一个XSLT,我需要根据文档元素的子元素数量在XSLT中做出决定。使用XSLT根据节点数量对条件进行XML转换

<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> 

即,根元素应被删除,如果其(唯一)子可以充当作为新的文件根目录o f应用XSLT后的结果XML。每个事件都必须删除<foo>节点。

有没有办法用一个XSL执行这个操作?

回答

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"/> 
+0

+1谢谢,似乎在我的沙箱里工作。我只是在学习XSLT:像[*和不...]这样的正则表达式需要XSLT 2.0吗? – msi 2012-03-18 14:05:02

+0

仅在XSLT和XPath 2.0中支持字符串匹配的正则表达式。然而,我只使用XSLT 1.0元素匹配模式作为match =“root [* [2]]”'只是'match =“root [child :: * [2]]的简写形式''意思是匹配'root '具有至少两个任何名字的子元素的元素。 – 2012-03-18 14:18:00

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. 第二个重写模板匹配顶层元素的大子元素的任何元素。该模板没有一个机构,这意味着所有这些匹配元素被忽略,且不包含在输出(换句话说 - “删除”)

请注意

无论文档中的元素名称如何,此转换都可以应用于任何 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>