We have a current system that outputs an XML file which is in the following format:
<INVENTORY>
<ITEM>
<SERIALNUMBER>something</SERIALNUMBER>
<LOCATION>something</LOCATION>
<BARCODE>something</BARCODE>
</ITEM>
</INVENTORY>
I need to use this data to load into the standard .NET 2.0 grid. But the grid needs the XML to be in the following format:
<INVENTORY>
<ITEM serialNumber="something" location="something" barcode="something">
</ITEM>
</INVENTORY>
i.e. the child nodes of item need to be converted into attributes of the item node.
Does someone know how this can be done using XSLT?
The standard way to transform XML data into other formats is by Extensible Stylesheet Language Transformations (XSLT). You can use the built-in XSLTRANSFORM function to convert XML documents into HTML, plain text, or different XML schemas. XSLT uses stylesheets to convert XML into other data formats.
XSLT is used to transform XML document from one form to another form. XSLT uses Xpath to perform matching of nodes to perform these transformation . The result of applying XSLT to XML document could be an another XML document, HTML, text or any another document from technology perspective.
XSLTJSON: Transforming XML to JSON using XSLTXSLTJSON is an XSLT 2.0 stylesheet to transform arbitrary XML to JavaScript Object Notation (JSON). JSON is a lightweight data-interchange format based on a subset of the JavaScript language, and often offered as an alternative to XML in—for example—web services.
XSLT <xsl:attribute> The <xsl:attribute> element is used to add attributes to elements. Note: The <xsl:attribute> element replaces existing attributes with equivalent names.
This should work:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="INVENTORY">
<INVENTORY>
<xsl:apply-templates/>
</INVENTORY>
</xsl:template>
<xsl:template match="ITEM">
<ITEM>
<xsl:for-each select="*">
<xsl:attribute name="{name()}">
<xsl:value-of select="text()"/>
</xsl:attribute>
</xsl:for-each>
</ITEM>
</xsl:template>
</xsl:stylesheet>
Here is probably the simplest solution that will convert any children-elements of ITEM
to its attributes and will reproduce everything else as is, while converting the element names to any desired attribute names:
<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:variable name="vrtfNameMapping">
<item name="SERIALNUMBER" newName="serialNumber"/>
<item name="LOCATION" newName="location"/>
<item name="BARCODE" newName="barcode"/>
</xsl:variable>
<!-- -->
<xsl:variable name="vNameMapping" select=
"document('')/*/xsl:variable[@name='vrtfNameMapping']"/>
<!-- -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- -->
<xsl:template match="ITEM/*">
<xsl:attribute name=
"{$vNameMapping/*[@name=name(current())]/@newName}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
when the above transformation is applied on the provided XML document:
<INVENTORY>
<ITEM>
<SERIALNUMBER>something</SERIALNUMBER>
<LOCATION>something</LOCATION>
<BARCODE>something</BARCODE>
</ITEM>
</INVENTORY>
the wanted result is produced:
<INVENTORY>
<ITEM serialNumber="something" location="something" barcode="something"/>
</INVENTORY>
Do note the following:
The use of the identity rule
The use of <xsl:strip-space elements="*"/>
The use of the variable vrtfNameMapping
without any xxx:node-set()
extension function.
The fact that we handle any mapping between a name and a newName, not only simple lower-casing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With