XML Starlet is a program that makes transforming XML documents really simple.
The command that you need to transform an XML document is the following.
xmlstarlet tr [<options>] <xsl-file> {-p|-s <name>=<value>} [ <xml-file-or-uri> ... ]
The XSL file that transforms a document to itself is this. It copies all elements, attributes and texts. We can extend this file to remove, add, or transform elements.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- IdentityTransform -->
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
To remove an element, we match an element and don’t call apply-elements inside it. This example will remove the remove me element.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- IdentityTransform -->
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<!-- Remove the element -->
<xsl:template match="remove-me">
</xsl:template>
</xsl:stylesheet>
To add an element, we just add the part we would like to add. If it needs to be in a certain place, we can add an extra
xsl:template
rule. The this-will-get-added
element will be inserted after the element
element.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- IdentityTransform -->
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="element">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
<this-will-get-added></this-will-get-added>
</xsl:template>
</xsl:stylesheet>
To transform an element we remove xsl:copy
and replace it with the
elements we need. If we keep the xsl:apply-elements
tag in the xsl:template
tag,
we copy everything inside the element in it’s place.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- IdentityTransform -->
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="element">
<my-new-element>
<xsl:apply-templates select="@* | node()" />
</my-new-element>
</xsl:template>
</xsl:stylesheet>
XSL used in this way becomes quite simple to use. With these three patterns we can extend the identity transformation and get quite a bit of power when we transform XML documents.