我正在尝试使用XSLT删除祖先标记(及其子代),因为它们具有空文本和特定属性值。我有XSLT检查每个节点的text(),当它是空的,祖先有属性deltaxml:deltaV2 =“A”我想删除祖先和子节点。
这是我要删除的xml标签(注意:祖先可以是任何不仅仅是'p')。在这种情况下,我想要删除最后一个p标签和子项:
<body>
<p deltaxml:deltaV2="A=B">
<t>This is the same</t>
</p>
<p deltaxml:deltaV2="B">
<t>This is inserted</t>
</p>
<p deltaxml:deltaV2="A">
<t>This is deleted</t>
</p>
<p deltaxml:deltaV2="A">
<t> </t>
</p>
</body>
这是我到目前为止的XSLT:
<xsl:template match="@* | * | processing-instruction() | comment()" mode="#all">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="@*, node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()">
<xsl:variable name="deltaV2" as="attribute()" select="ancestor::*[@deltaxml:deltaV2][1]/@deltaxml:deltaV2"/>
<xsl:variable name="text" select="."/>
<xsl:choose>
<xsl:when test="$deltaV2 eq 'A'">
<xsl:choose>
<xsl:when test="$text = ' '">
<!-- need to remove ancestor tags-->
</xsl:when>
<xsl:otherwise>
<xsl:element name="delete" namespace="{$root-ns}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$deltaV2 eq 'B'">
<xsl:element name="insert" namespace="{$root-ns}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
这是期望的输出:
<body>
<p deltaxml:deltaV2="A=B">
<t>This is the same</t>
</p>
<p deltaxml:deltaV2="B">
<t><insert>This is inserted</insert></t>
</p>
<p deltaxml:deltaV2="A">
<t><delete>This is deleted</delete></t>
</p>
</body>
我需要这个的原因是因为这些属性显示在两个版本的XML之间是否插入或删除了某些内容,但是如果有一个空节点(即样本中的空t标签)我不想跟踪这是一个变化,因为没有文字发生变化,只是希望删除。 当文本为空时我需要放置什么才能删除这些标签?
答案 0 :(得分:1)
当我们有空文本和特定属性值时,我试图使用XSLT删除[...]标签(及其子代)。
执行此操作的模板非常简单
<xsl:template match="*[@deltaxml:deltaV2 = 'A' and normalize-space() = '']" />
将其与身份转换一起使用。在这里阅读有关身份转换的信息:http://www.dpawson.co.uk/xsl/sect2/identity.html(您最喜欢的搜索引擎将提供的无数其他示例)。
此处关于SO的问题也为您所描述的同一问题提供了规范性答案:How to remove elements from xml using xslt with stylesheet and xsltproc?
答案 1 :(得分:0)
您无法删除处理后代的模板中的祖先。当样式表到达空text()
节点时,p
祖先已经处理并写入输出树 - 请参阅:https://www.w3.org/TR/xslt/#section-Processing-Model
如果您重申您的要求:删除满足两者的任何元素(及其所有后代):
deltaxml:deltaV2
的属性,其值为“A”; 然后您可以将其实现为:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:deltaxml="http://example.com/deltaxml">
<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="*[@deltaxml:deltaV2='A'][.//*[not(normalize-space())]]" />
</xsl:stylesheet>
当然,您需要将deltaxml:
前缀绑定到输入XML中使用的相同名称空间URI,而不是像我在此处所做的任意名称。