如何在XSL中筛选?
问题描述:
我正在学习XSLT,并试图过滤现有的XML文件,并且基本上只复制具有感兴趣的选定节点的树 - 如果它们匹配条件,比如说有子串“测试”。如何在XSL中筛选?
使用恒等变换模式,我有以下片段:
<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>
答
,后代元素名称和后代处理指令名称,你必须明确地这样做。您的代码仅检查当前节点的名称。如果要匹配属性名称,则需要确保属性所附的元素不能被丢弃。例如:
<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函数。因此,对于所有匹配的元素,元素的字符串值(即所有文本节点连接起来)将输出到元素的位置。对于匹配的属性,注释,处理指令和文本节点,由于copy
元素忽略了其节点类型的内容,因此不会输出其他文本。
答
使用本
<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>
如果你想匹配的祖先元素的名称,它会给你的愿望输出
请提供您的XML文件。 – AntonH
@AntonH我编辑了这个问题,并用XML片段进行了更新。我正在寻找这种问题的通用解决方案,因此它应该足够灵活以适应其他类型的XML结构。 – WCGPR0