我正在学习XSLT并且正在尝试过滤现有的XML文件,并且基本上仅使用选定的感兴趣节点复制树 - 如果它们匹配条件,则说子字符串为'test'。
使用身份转换模式,我有以下代码段:
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="(node() | @*)[contains(name(.), 'test')]" />
<!-- Bonus Q: What would be happening behind the scenes when I put this code inside the copy element?
<xsl:value-of select="." /> -->
</xsl:copy>
</xsl:template>
现在这让我得到以下输出,
<head>
<testA> <testAChild /></testA> <!-- should be <testA> <testAChild> foo </testAChild></testA> -->
<testB /> <!-- should be <testB> bar </testB> -->
<Ctest /> <!-- should be <Ctest> foobar </Ctest> -->
<!-- should be <DontDeleteThis> <testD> 420 </testD></DontDeleteThis> -->
</head>
但是,它在结果树中没有值。此外,在当前节点为假但子女,孙子女或可能的大孩子可以通过标准时,不会检查每个案例。
以下是输入XML的示例:
<head>
<testA>
<testAChild> foo </testAChild>
</testA>
<testB> bar </testB>
<Ctest> foobar </Ctest>
<DeleteThis> DELETED </DeleteThis>
<DontDeleteThis>
<testD> 420 </testD>
</DontDeleteThis>
</head>
答案 0 :(得分:1)
使用此
<xsl:template match="node()">
<xsl:copy>
<xsl:apply-templates select="node()[descendant-or-self::*[contains(name(.), 'test')]]" />
</xsl:copy>
</xsl:template>
<xsl:template match="node()[contains(name(.), 'test')]">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
它会给你的欲望输出
答案 1 :(得分:1)
如果要匹配祖先元素名称,后代元素名称和后代处理指令名称,则必须明确地这样做。您的代码仅检查当前节点的名称。如果要匹配属性名称,则需要确保不能丢弃属性所附加的元素。例如:
<transform xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0" xml:lang="en-latn">
<output media-type="application/xml"/>
<template match="attribute::node() | child::node()">
<copy>
<variable name="attributes" select="attribute::node()[contains(name(), 'test')]"/>
<variable name="elements" select="child::*[count((descendant-or-self::node() | attribute::node())[contains(name(), 'test')]) > 0]"/>
<variable name="comments" select="child::comment()[count(ancestor::node()[contains(name(), 'test')]) > 0]"/>
<variable name="PIs" select="child::processing-instruction()[count(ancestor-or-self::node()[contains(name(), 'test')]) > 0]"/>
<variable name="text" select="child::text()[count(ancestor::node()[contains(name(), 'test')]) > 0]"/>
<apply-templates select="$attributes | $elements | $comments | $PIs | $text"/>
</copy>
</template>
</transform>
另外值得注意的是,Rupesh的代码与处理指令(PI)节点名称不匹配。 *
和node()
之间存在细微差别; *
是除attribute
和namespace
轴之外的元素节点的简写,这意味着您必须使用node()
来匹配PI节点。 (在XPath 2中,*
/ element()
中有element(*)
的相应缩写。我想知道这会让这个概念变得更加混乱。)
至于您的红利问题,value-of
元素在所选节点上运行string
XPath函数。因此,对于所有匹配的元素,元素的字符串值(即,其连接的所有文本节点)将在value-of
元素的位置输出。对于匹配的属性,注释,处理指令和文本节点,不会输出其他文本,因为copy
元素忽略了这些节点类型的内容。