我有一个遵循这个整体模式的xml文档:
<A b="c" d="e" f="g" h="i">
<!-- plenty of children -->
</A>
我想复制A
节点只包含其中的一些属性:
<A b="c" f="g">
<!-- some of the children -->
</A>
这里的其他答案已接近解决我的挑战,但还不够:
<xsl:copy-of select="@*[(name()!='d') or (name()!='h']"/>
,但我的实际属性列表很长。请帮忙
答案 0 :(得分:3)
您链接的白名单解决方案使用包含应保留的元素列表的嵌入式文档。您的属性可以有类似的属性:
<myns:whitelist>
<keep>b</keep>
<keep>f</keep>
</myns:whitelist>
可以使用document('')
函数加载和解析它,您可以将其存储在变量中,以便更容易引用它:
<xsl:variable name="keep" select="document('')/*/myns:whitelist/keep"/>
现在$keep
变量包含列表中所有属性的名称。星号表示<xsl:stylesheet>
元素,因为传递给document()
的参数是一个空字符串,这会导致它从当前文档加载。
然后,您可以测试任意atrributes的名称是否与$keep
node-set中的任何名称匹配:
@*[name()=$keep]
使用身份转换复制的其他人。
以下是您提供的示例的完整样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:myns="myns">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<myns:whitelist>
<keep>b</keep>
<keep>f</keep>
</myns:whitelist>
<xsl:variable name="keep" select="document('')/*/myns:whitelist/keep"/>
<xsl:template match="A">
<xsl:copy>
<xsl:apply-templates select="node()|@*[name()=$keep]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:2)
通常,如果您想从输入中删除某些内容,请为要删除的内容编写一个空模板:
<!-- drop every attribute of <A> ... -->
<xsl:template match="A/@*" />
另一个非空的模板,用于保存您的内容:
<!-- ... except @b and @f -->
<xsl:template match="A/@b | A/@f">
<xsl:copy-of select="." />
</xsl:template>
然后只需正常应用模板:
<xsl:template match="A">
<xsl:copy>
<xsl:apply-templates select="@*" />
<!-- other output -->
</xsl:copy>
</xsl:template>
总而言之,这已经做对了。
提示:如果您的样式表中有一个身份模板,并且不需要对<A>
进行其他更改,那么您甚至不需要第三个模板。
答案 2 :(得分:1)
如果您正在使用XSLT 2.0,则可以使用序列。如果您将其放在xsl:param
而不是xsl:variable
中,则可以在运行时定义白名单(如果需要)。
示例:
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="whitelist" select="('b','f')"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="A">
<xsl:copy>
<xsl:apply-templates select="@*[name()=$whitelist]|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>