Reputation: 55
I will need to skip first Worker
node and copy rest of the nodes using XSLT 3.0
My source XML is
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<Employee>Emp</Employee>
<ID>Identifier</ID>
</Worker>
<Worker>
<Employee>12344</Employee>
<ID>1245599</ID>
</Worker>
<Worker>
<Employee>25644</Employee>
<ID>7823565</ID>
</Worker>
</Workers>
and desired output is
<?xml version="1.0" encoding="utf-8"?>
<Workers>
<Worker>
<Employee>12344</Employee>
<ID>1245599</ID>
</Worker>
<Worker>
<Employee>25644</Employee>
<ID>7823565</ID>
</Worker>
</Workers>
and XSLT that i have is
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="Worker[position() = 1]"/>
</xsl:stylesheet>
Above XSLT produces the output that I was expecting but I'm looking to see if there is a better way to skip the first node without using postion()
as I'm not sure how efficient my current code is to process large files( approximately 800 MB)
I had to use following to remove white spaces from my result XML
<xsl:strip-space elements="*"/>
Can anyone check my code and provide any suggestion to improvise my code please?
===============
With Michael Kay's suggestion, my code looks like this
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" indent="yes"/>
<!-- <xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template> -->
<!-- Removed above Identity Transformation -->
<xsl:mode streamable="yes" on-no-match="shallow-copy"/>
<xsl:template match="Workers">
<xsl:copy>
<xsl:apply-templates select="tail(Worker)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Views: 363
Reputation: 163342
I would write it
<xsl:template match="Worker[1]"/>
for readability, but it's all the same.
Match patterns with positional predicates can perform badly, so you're right to be cautious, but a simple one like this should be OK. In fact the main adverse consequence is probably that Saxon will allocate preceding-sibling pointers in the TinyTree, so that it can compute the node's sibling position.
Saxon effectively implements it as
<xsl:template match="Worker[not(preceding-sibling::Worker)]"/>
and you might prefer to write it that way. However, neither form is streamable.
To make it streamable, you could drop the unwanted nodes by not selecting them:
<xsl:template match="Workers">
<xsl:copy>
<xsl:apply-templates select="tail(Worker)"/>
</xsl:copy>
</xsl:template>
which might also be fractionally faster in the non-streaming case; and it saves memory because preceding-sibling pointers aren't needed.
Upvotes: 1