Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting XML elements to XML attributes using XSLT

Tags:

xml

xslt

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?

like image 630
eMTeeN Avatar asked Mar 17 '09 18:03

eMTeeN


People also ask

How do I transfer XML from one XML to another using XSLT transform?

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.

How XML transformations is done using XSLT explain?

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.

Can XSLT transform XML to JSON?

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.

What is attribute in XSLT?

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.


2 Answers

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>
like image 171
Johannes Weiss Avatar answered Sep 28 '22 00:09

Johannes Weiss


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:

  1. The use of the identity rule

  2. The use of <xsl:strip-space elements="*"/>

  3. The use of the variable vrtfNameMapping without any xxx:node-set() extension function.

  4. The fact that we handle any mapping between a name and a newName, not only simple lower-casing.

like image 41
Dimitre Novatchev Avatar answered Sep 28 '22 00:09

Dimitre Novatchev