我创建了一个样式表,该样式表应该有选择地复制 XML 文档的内容,以便我可以删除不需要的数据。我在下面提供了 2 个示例以及我们当前用于执行此操作的样式表。样式表有效,但我认为可能有更好的方法,因为在当前版本中,我在两个不同的位置检查相同的内容(author='John Doe')。
在输出中包含 xml 元素的规则如下:
- 如果记事本中存在一个记事本元素,其作者文本等于“John Doe”,则在输出中包含该记事本元素
- 如果记事本元素的作者元素的文本等于“John Doe”,则将记事本元素中的所有元素包含在 xml 输出中。
输入示例#1
<transaction>
<policy>
<insco>CC</insco>
<notepads>
<notepad>
<author>Andy</author>
<notepad>
<notepad>
<author>John Doe</author>
<notepad>
<notepad>
<author>Barney</author>
<notepad>
</notepads>
</policy>
</transaction>
输入 #1 的预期结果
<transaction>
<policy>
<insco>CC</insco>
<notepads>
<notepad>
<author>John Doe</author>
<notepad>
</notepads>
</policy>
</transaction>
输入示例#2
<transaction>
<policy>
<insco>CC</insco>
<notepads>
<notepad>
<author>Andy</author>
<notepad>
</notepads>
</policy>
</transaction>
输入 #2 的预期结果
<transaction>
<policy>
<insco>CC</insco>
</policy>
</transaction>
样式表的当前版本
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="fn">
<xsl:template match="*">
<xsl:choose>
<xsl:when test="name()='notepads'">
<xsl:if test="/transaction/policy/insco='CC' and (notepad/author='John Doe')">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:if>
</xsl:when>
<xsl:when test="name()='notepad'">
<xsl:if test="author='John Doe'">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
最佳答案
我可以想到两种方法来做到这一点。
1)身份模板,硬编码作者姓名:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- nodepads generally get removed... -->
<xsl:template match="notepad" />
<!-- ...unless their author is 'Jon Doe' -->
<xsl:template match="notepad[author='John Doe']">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>
2) 修改身份模板、XSL key 、参数化作者姓名:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:param name="theAuthor" select="'John Doe'" />
<xsl:key
name="kNotepad" match="notepad[author]"
use="concat(generate-id(..), '|', author)"
/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="
node()[not(self::notepad)]
|key('kNotepad', concat(generate-id(), '|', $theAuthor))
|@*"
/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
第二种方法需要一些解释:
<xsl:key>
索引全部<nodepad>
具有<author>
的节点通过 parent 的唯一 ID 和作者姓名- 假设唯一 ID
<notepads>
是'id0815'
,然后是<notepad>
的 key 您感兴趣的将是'id0815|Jon Doe'
- 身份模板复制通过它的每个节点。它的修改方式是不传递通过自身找到的每个节点,而只是:
- 不是
<notepad>
的任何节点:node()[not(self::notepad)]
- 任何属性:
@*
- 键返回的任何节点。
- 不是
- 调用
key()
自然只会在<notepads>
上返回任何内容元素(因为它包含它们的唯一ID) - 所以当模板当前正在处理
<notepads>
时元素('id0815'
在我们的例子中),key()
将返回其'Jon Doe'
仅限 child ,在所有其他情况下它将显示为空 - 与解决方案 1)相反,可以向此方案提供参数,从而在不更改代码的情况下更改其行为
- 值得注意的是,所有内容都保持输入文档顺序
关于xslt - 性能更高的 XSLT——选择性包含在输出中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2276202/