代码之家  ›  专栏  ›  技术社区  ›  developer

的XSL副本中的XPath祖先和后代

  •  5
  • developer  · 技术社区  · 14 年前

    我是XPath新手,从我在一些关于axes的教程中读到的内容来看,我仍然在想如何实现它们。他们的行为不像我预料的那样。我对使用祖先轴和后代轴特别感兴趣。

    我有以下XML结构:

    <file>
        <criteria>
            <root>ROOT</root>
            <criterion>AAA</criterion>
            <criterion>BBB</criterion>
            <criterion>CCC</criterion> 
        </criteria>
        <format>
            <sort>BBB</sort>
        </format>
    </file>
    

    我有以下XSL:

    <xsl:template match="/">
        <xsl:copy-of select="ancestor::criterion/>
    </xsl:template>
    

    什么也不产生!

    我希望它能产生:

    <file>
        <criteria>
        </criteria>
    </file>
    

    有人能用比我以前读过的教程更有用的方式向我解释祖先轴和后代轴吗?

    谢谢!

    2 回复  |  直到 14 年前
        1
  •  5
  •   Dimitre Novatchev    14 年前

    我有以下XSL:

    <xsl:template match="/"> 
        <xsl:copy-of select="ancestor::criterion/> 
    </xsl:template>
    

    什么也不产生!

    应该的!

    ancestor::criterion
    

    是一个相对表达式,这意味着它是根据当前节点计算的(由模板匹配)。但当前节点是文档节点 / .

    因此,上述相当于:

    /ancestor::criterion
    

    但是,根据定义,文档节点 /

    <file> 
        <criteria> 
        </criteria> 
    </file>
    

    你可能想要的是:

    //criterion/ancestor::*
    

    //*[descendant::criterion]
    

    最后两个XPath表达式是等效的,并选择具有 criterion

    最后,要产生您想要的输出,这里有一个可能的解决方案:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:template match="node()|@*">
      <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
     </xsl:template>
    
     <xsl:template match="root | criterion | format"/>
    </xsl:stylesheet>
    

    将此转换应用于提供的XML文档时,将生成所需的输出 :

    <file>
    <criteria>
    </criteria>
    </file>
    
        2
  •  1
  •   Welbog    14 年前

    ancestor 用于选择XML文档中更高(更接近根)的节点。 descendant

    在你的例子中, ancestor::criterion / (指文件的根)- <file> 在这种情况下),如 match="/" . 根节点没有祖先,因此 祖先 axis什么也不做。

    得到每一个 <criterion> 坐标轴:

    <xsl:template match="/">
      <xsl:copy-of select="descendant::criterion"/>
    </xsl:template>
    

    // :

    <xsl:template match="/">
      <xsl:copy-of select="//criterion"/>
    </xsl:template>
    

    <criterion>AAA</criterion>
    

    使用循环或其他模板,您可以获得所有三个:

    <xsl:template match="/">
      <file>
        <xsl:apply-templates select="//criterion"/>
      </file>
    </xsl:template>
    <xsl:template match="criterion">
      <xsl:copy-of select="."/>
    </xsl:template>
    

    这将产生以下结果:

    <file>
      <criterion>AAA</criterion>
      <criterion>BBB</criterion>
      <criterion>CCC</criterion> 
    </file>
    

    <文件> 元素,也有点复杂。XPath指定节点,简单副本不会复制包含所选元素的元素。如果你还不明白的话,我可以进一步澄清这一点。