XPath表达式/ node()[1]选择多于第一个节点?

时间:2017-01-20 01:36:55

标签: xml xslt xpath predicate

我有一份文件doc.xml

<?xml version="1.0"?>
<!-- This is the first top-level node -->
<!-- This is the second top-level node -->
<ThirdNode/>
<!-- This is the fourth top-level node -->

我想在firstnode.xsl中选择文档中的第一个顶级节点:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/node()[1]">First</xsl:template>
    <xsl:template match="@*|node()">
        <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
    </xsl:template>
</xsl:stylesheet>

当我运行xsltproc firstnode.xsl doc.xml时,我得到:

<?xml version="1.0"?>
FirstFirst<ThirdNode/><!-- This is the fourth top-level node -->

...而不是预期的输出:

<?xml version="1.0"?>
First
<!-- This is the second top-level node -->
<ThirdNode/>
<!-- This is the fourth top-level node -->

为什么/node()[1]选择器匹配的不仅仅是第一条评论?如何选择文档的第一个节点(无论是注释,元素还是其他)?

2 个答案:

答案 0 :(得分:3)

我已设法使用libxlt处理器重现您的问题,但未使用XalanSaxon重现您的问题 - 这使我得出结论认为这是不合规的行为。

将匹配模式更改为:

<xsl:template match="node()[not(parent::*)][1]">

似乎绕过了这个问题。

令人惊讶的是,甚至在原始表达中添加了虚假条件,例如:

<xsl:template match="/node()[not(0)][1]">

甚至:

<xsl:template match="/node()[1][1]">

也有效,所以这显然是一个错误。

答案 1 :(得分:0)

我不确定我是否正确理解了你的问题。但是,我试图重现你的问题,结果如下:

Input.xml

<?xml version="1.0"?>
<First>
  <Second>
    <ThirdNode/>      
    <Fourth />
  </Second>
</First>

<强> Processing.xslt

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/node()[1]">First1
      <xsl:apply-templates select="node()|@*" />
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
    </xsl:template>

</xsl:stylesheet>

<强>输出

<?xml version="1.0"?>
First1

  <Second>
    <ThirdNode/>      
    <Fourth/>
  </Second>

也许这会以某种方式帮助你。