As you didn't specify the XSLT version, I used version 2.0.
Note that your source XML uses the default namespace of
http://www.force.com/2009/06/asyncapi/dataload, so generally you should
mention it in stylesheet XSLT element.
But to simplify the script, you can specify it as xpath-default-namespace,
so you do not need to specify it as a "regular" namespace.
The idea to write the script is simple: write a template matching records
(in the default namespace, as specified before). This template shoud:
- Copy the source opening tag.
- Apply templates to the first
id child element.
- Apply templates to all child elements, except
id.
- Copy the source closing tag.
Your script should include also the identity template.
So the whole script can be as follows:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://www.force.com/2009/06/asyncapi/dataload">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="records">
<xsl:copy>
<xsl:apply-templates select="id[1]"/>
<xsl:apply-templates select="* except id"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>
For a working example see http://xsltransform.net/pNvs5wD
Edit
Another solution is to write an empty template matching id,
which has preceding-sibling element with name id:
<xsl:template match="id[preceding-sibling::id]"/>
So the whole script can be:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://www.force.com/2009/06/asyncapi/dataload">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="id[preceding-sibling::id]"/>
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
</xsl:stylesheet>
The difference is that this time you keep the order of child elements,
whereas the first solution "moves" the id element to the beginning.
Note: This time I added <xsl:strip-space elements="*"/> to avoid empty
lines in the output.