XPath 表达式 /node()[1] 选择多于第一个节点?
XPath expression /node()[1] selects more than the first node?
我有一个文件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 -->
我想要 select 文档中的第一个顶级节点,在 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]
selector 匹配的不仅仅是第一条评论?我如何 select 文档的第一个节点(无论它是注释、元素还是其他)?
我不确定我是否正确理解了你的问题。然而,我试图重现你的问题,结果是这样的:
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>
也许这对你有帮助。
我已经成功地使用 libxlt
处理器重现了您的问题,但没有使用 Xalan
或 Saxon
- 这让我得出结论,这是 non-conforming 行为.
将匹配模式更改为:
<xsl:template match="node()[not(parent::*)][1]">
似乎绕过了这个问题。
令人惊讶的是,甚至在您的原始表达式中添加了虚假条件,例如:
<xsl:template match="/node()[not(0)][1]">
甚至:
<xsl:template match="/node()[1][1]">
也有效,所以这显然是一个错误。
我有一个文件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 -->
我想要 select 文档中的第一个顶级节点,在 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]
selector 匹配的不仅仅是第一条评论?我如何 select 文档的第一个节点(无论它是注释、元素还是其他)?
我不确定我是否正确理解了你的问题。然而,我试图重现你的问题,结果是这样的:
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>
也许这对你有帮助。
我已经成功地使用 libxlt
处理器重现了您的问题,但没有使用 Xalan
或 Saxon
- 这让我得出结论,这是 non-conforming 行为.
将匹配模式更改为:
<xsl:template match="node()[not(parent::*)][1]">
似乎绕过了这个问题。
令人惊讶的是,甚至在您的原始表达式中添加了虚假条件,例如:
<xsl:template match="/node()[not(0)][1]">
甚至:
<xsl:template match="/node()[1][1]">
也有效,所以这显然是一个错误。