2017-02-22 139 views
0

我正在学习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> 
+0

请提供您的XML文件。 – AntonH

+0

@AntonH我编辑了这个问题,并用XML片段进行了更新。我正在寻找这种问题的通用解决方案,因此它应该足够灵活以适应其他类型的XML结构。 – WCGPR0

回答

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()之间存在细微的差异; *是元素节点的简写,除了attributenamespace轴之外,这意味着您必须使用node()来匹配PI节点。 (在XPath 2,有一个在element()/element(*)*相应的草书,我想知道,使这一概念少一点混乱。)

至于你的奖金问题,value-of元素运行选择的节点上string XPath函数。因此,对于所有匹配的元素,元素的字符串值(即所有文本节点连接起来)将输出到元素的位置。对于匹配的属性,注释,处理指令和文本节点,由于copy元素忽略了其节点类型的内容,因此不会输出其他文本。

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> 

如果你想匹配的祖先元素的名称,它会给你的愿望输出