Xml XSLT-删除没有与特定值匹配的子节点的节点
我对XSLT非常陌生,我昨天开始阅读有关它的文章,我被卡住了。我有以下XMLXml XSLT-删除没有与特定值匹配的子节点的节点,xml,xslt,xpath,Xml,Xslt,Xpath,我对XSLT非常陌生,我昨天开始阅读有关它的文章,我被卡住了。我有以下XML <?xml version="1.0" encoding="utf-8" ?> <Menu> <Function> <Name>ViewHome</Name> <Roles> <Role>Finance</Role> <Role>Advisor</Role>
<?xml version="1.0" encoding="utf-8" ?>
<Menu>
<Function>
<Name>ViewHome</Name>
<Roles>
<Role>Finance</Role>
<Role>Advisor</Role>
<Role>Admin</Role>
</Roles>
</Function>
<Function>
<Name>ViewStaff</Name>
<ChildFunctions>
<Function>
<Name>StaffFunction1</Name>
<Roles>
<Role>Finance</Role>
</Roles>
</Function>
<Function>
<Name>StaffFunction2</Name>
<Roles>
<Role>Admin</Role>
</Roles>
</Function>
<Function>
<Name>StaffFunction3</Name>
<Roles>
<Role>Advisor</Role>
</Roles>
</Function>
</ChildFunctions>
</Function>
<Function>
<Name>ViewDiary</Name>
<Roles>
<Role>Advisor</Role>
</Roles>
</Function>
</Menu>
观景屋
财务
顾问
管理
视杆
员工职能1
财务
员工职能2
管理
职员职能3
顾问
查看日记
顾问
我希望将其转换为仅显示那些包含指定角色的函数(父函数或子函数)。因此,如果应用财务和顾问角色,则输出将如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<Menu>
<Function>
<Name>ViewHome</Name>
<Roles>
<Role>Finance</Role>
<Role>Advisor</Role>
</Roles>
</Function>
<Function>
<Name>ViewStaff</Name>
<ChildFunctions>
<Function>
<Name>StaffFunction1</Name>
<Roles>
<Role>Finance</Role>
</Roles>
</Function>
<Function>
<Name>StaffFunction3</Name>
<Roles>
<Role>Advisor</Role>
</Roles>
</Function>
</ChildFunctions>
</Function>
<Function>
<Name>ViewDiary</Name>
<Roles>
<Role>Advisor</Role>
</Roles>
</Function>
</Menu>
观景屋
财务
顾问
视杆
员工职能1
财务
职员职能3
顾问
查看日记
顾问
我看过这个网站上的其他帖子,但无法生成所需的输出。我一直在使用的xsl是:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:variable name="rolesList">Advisor Finance</xsl:variable>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Function[not(descendant::Role[contains($rolesList, .)])]"/>
<!--
<xsl:template match="Function[not(descendant::Role='Finance')]"/>
-->
</xsl:stylesheet>
财务顾问
最终rolesList变量将通过代码提供。我只是想让转换工作起来。如果我只为“财务”角色使用注释掉的模板匹配,我会得到预期的结果。
非常感谢您的帮助。如果有多个Role
元素,我怀疑contains()无法正常工作,因为函数不希望列表作为其第二个参数
请注意,您提供的角色列表是一个以空格分隔的列表。然而,如果没有模式,它就不能被识别为列表类型。正如@michael.hor257k所指出的,这就是为什么必须依赖字符串函数
正如@timc所指出的,这(即包含变量的模板匹配)只适用于XSLT2.0
使用以下样式表:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="roles">Finance Advisor</xsl:variable>
<xsl:template match="Function[count(Roles/Role) = 1 and not(matches($roles,Roles/Role))]"/>
<xsl:template match="Role[not(matches($roles,.))]"/>
</xsl:stylesheet>
财务顾问
输出
<?xml version="1.0" encoding="UTF-8"?>
<Menu>
<Function>
<Name>ViewHome</Name>
<Roles>
<Role>Finance</Role>
<Role>Advisor</Role>
</Roles>
</Function>
<Function>
<Name>ViewStaff</Name>
<ChildFunctions>
<Function>
<Name>StaffFunction1</Name>
<Roles>
<Role>Finance</Role>
</Roles>
</Function>
<Function>
<Name>StaffFunction3</Name>
<Roles>
<Role>Advisor</Role>
</Roles>
</Function>
</ChildFunctions>
</Function>
<Function>
<Name>ViewDiary</Name>
<Roles>
<Role>Advisor</Role>
</Roles>
</Function>
</Menu>
观景屋
财务
顾问
视杆
员工职能1
财务
职员职能3
顾问
查看日记
顾问
我想将其转换为仅显示那些函数(父函数或
包含一个或多个指定角色的
我相信您的样式表确实做到了这一点(,尽管它不应该这样做,而且只针对某些处理器-有关更多详细信息,请参阅问题的注释)
但是,它不会从通过测试的函数的子代角色列表中删除“其他”角色。为此,您需要添加另一个模板匹配角色
最终rolesList变量将通过代码提供
理想情况下,列表将作为节点集(或可以转换为节点集的内容)提供,这样您就可以进行比较,而无需使用字符串函数。但是,在XSLT2.0中,在这方面有更大的灵活性。在XSLT1.0中,可以使用字符串比较
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:param name="roleList" select="'|Advisor|Finance|'"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Function">
<xsl:if test="descendant::Role[contains($roleList, concat('|', ., '|'))]">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
<xsl:template match="Role">
<xsl:if test="contains($roleList, concat('|', ., '|'))">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
使用内部查找列表:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="your-urn-here">
<my:rolesList>
<my:role>Advisor</my:role>
<my:role>Finance</my:role>
</my:rolesList>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Function[not(descendant::Role = document('')/*/my:rolesList/my:role)]"
/>
</xsl:stylesheet>
顾问
财务
您能在这里使用XSLT 2.0吗?在XSLT1.0中,不可能在模板匹配中使用变量,但在XLST2.0中是这样。另一方面,在模板匹配中,您指的是roleList,但该变量实际上名为roleList!Tim,我对使用哪个版本的XSL没有限制。感谢您注意到输入错误。您可以指定不应出现在输出中的角色吗?@TimC“在XSLT 1.0中,无法在模板匹配中使用变量。请原谅,我没有正确表达。应该理解为“您不能在xsl:template
命令的match
属性中使用变量。”