XSLT for segmenting XML
I have an XML that goes like this:
<company>
<employee name="john"/>
<employee name="sarah"/>
<employee name="kim"/>
<employee name="karl"/>
<employee name="tom"/>
<employee name="jim"/>
<employee name="sandy"/>
</company>
How can I use a XSLT template for selectin开发者_开发百科g just the first n nodes, 3 for example, so I can get:
<company>
<employee name="john"/>
<employee name="sarah"/>
<employee name="kim"/>
</company>
In Oxygen XML editor, I can use the following XPath to achieve that:
/company/employee[position() < (last() - count(/company/employee)+4)]
but I really need to use XSLT in this case
Thanks for your helpHow can I use a XSLT template for selecting just the first n nodes, 3 for example, so I can get:
<company> <employee name="john"/> <employee name="sarah"/> <employee name="kim"/> </company>
The short answer: By knowing just a little bit XPath and XSLT.
Complete(but still short) answer:
This transformation:
<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="employee[position() > 3]"/>
</xsl:stylesheet>
when applied on the provided XML document:
<company>
<employee name="john"/>
<employee name="sarah"/>
<employee name="kim"/>
<employee name="karl"/>
<employee name="tom"/>
<employee name="jim"/>
<employee name="sandy"/>
</company>
produces the wanted, correct result:
<company>
<employee name="john"/>
<employee name="sarah"/>
<employee name="kim"/>
</company>
Do note:
The identity rule is used to copy every node "as-is".
There is just one specific template overriding the identity template. It matches any
employee
element with position in the node-list greater than 3. This template has an empty body, effectively discarding the matched elements.
I can use the following XPath to achieve that:
/company/employee[position() < (last() - count(/company/employee)+4)]
Do note that here last()
is equal to count(/company/employee)
, so this will be reduce to:
/company/employee[4 > position()]
In a pattern you could have:
<xsl:template match="employee[4 > position()]">
...
</xsl:template>
The same with parametrization (Remenber you can't use parameter reference in XSLT 1.0 patterns):
<xsl:param name="pTop" select="3"/>
<xsl:template match="employee">
<xsl:if test="$pTop >= position()">
...
</xsl:if>
</xsl:template>
Try this:
<xsl:for-each select="company/employee[position() < 3]">
...
</xsl:for-each>
This might work with <template select=....
too but i'm not sure.
精彩评论