xsl 问题:仅删除不包含特定节点的分支

Problem with xsl: remove only the branch that does not contain a particular node

我只想删除没有用户节点的区域

我的起始 xml 文件 XML:

<root>
    <area_1>
        <role_1>
            <user>
                <name>william</name>
            </user>
        </role_1>
        <role_2>
            <user>
                <name>william</name>
            </user>
        </role_2>
    </area_1>
    <area_2>
        <role_1 />
        <role_2>
            <user>
                <name>william</name>
            </user>
        </role_2>
    </area_2>
    <area_3>
        <role_1 />
    </area_3>
</root>

这是 XSL:

<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="*[not(descendant::text() or descendant-or-self::*/@*[string()])]" />
    <xsl:template match="@*[not(string())]" />
</xsl:stylesheet>

这里我丢了用户节点所在区域的规则

输出XML:

<root>
   <area_1>
      <role_1>
         <user>
            <name>william</name>
         </user>
      </role_1>
      <role_2>
         <user>
            <name>william</name>
         </user>
      </role_2>
   </area_1>
   <area_2>
      <role_2>
         <user>
            <name>william</name>
         </user>
      </role_2>
   </area_2>
</root>

我的问题:

我想保留各个分支的角色,只删除没有节点用户的区域。

我想得到这个结果:

<root>
    <area_1>
        <role_1>
            <user>
                <name>william</name>
            </user>
        </role_1>
        <role_2>
            <user>
                <name>william</name>
            </user>
        </role_2>
    </area_1>
    <area_2>
        <role_1 /> <!--keep these tags-->
        <role_2>
            <user>
                <name>william</name>
            </user>
        </role_2>
    </area_2>
</root>

我如何修改我的 xsl? 谢谢

remove only the areas that do not have the node user.

我相信这会转化为:

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="area[not(descendant::user)]"/>

</xsl:stylesheet>

但是由于您没有任何实际命名为 area 的元素,您将需要执行如下操作:

<xsl:template match="*[starts-with(name(), 'area')][not(descendant::user)]"/>

或者也许:

<xsl:template match="/root/*[not(descendant::user)]"/>

谢谢 michael.hor257k

我用过:

<xsl:template match="/root/*[not(descendant::user)]"/>