Reputation: 7582
I have a document 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 -->
I'd like to select the first top-level node from the document, in 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>
When I run xsltproc firstnode.xsl doc.xml
, I get:
<?xml version="1.0"?>
FirstFirst<ThirdNode/><!-- This is the fourth top-level node -->
… instead of the expected output:
<?xml version="1.0"?>
First
<!-- This is the second top-level node -->
<ThirdNode/>
<!-- This is the fourth top-level node -->
Why does the /node()[1]
selector match more than just the first comment? How can I select the first node of the document (regardless of whether it is a comment, element, or whatever)?
Upvotes: 0
Views: 334
Reputation: 117165
I have managed to reproduce your problem using the libxlt
processor, but not with Xalan
or Saxon
- which leads me to conclude that this is non-conforming behavior.
Changing the match pattern to:
<xsl:template match="node()[not(parent::*)][1]">
seems to bypass the issue.
Surprisingly, even adding a bogus condition to your original expression, such as:
<xsl:template match="/node()[not(0)][1]">
or even:
<xsl:template match="/node()[1][1]">
also works, so this is clearly a bug.
Upvotes: 3
Reputation: 29052
I am not sure if I did correctly understand your question. However, I tried to reproduce your question and the result was this:
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>
Output:
<?xml version="1.0"?>
First1
<Second>
<ThirdNode/>
<Fourth/>
</Second>
Maybe this helps you in some way.
Upvotes: 0