Search code examples
xmlxsltmicrosoft-dynamics-nav

Converting XML with XSLT transformation


I am trying to convert xml to xsl. This is my xml file.

<?xml version="1.0" encoding="UTF-8"?>
<ml_root>
    <entry xmlns="http://www.w3.org/2005/Atom"
        xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
        xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
        xml:base="http://ta-nb-manill.totalamber.com:7048/DynamicsNAV90/OData/"
        m:etag="W/&quot;'28%3BDgAAAAJ7%2F0IATABVAEUAAAAAAA%3D%3D6%3B1604150%3B'&quot;">
        <id>http://ta-nb-manill.totalamber.com:7048/DynamicsNAV90/OData/Company('CRONUS%20International%20Ltd.')/Location('BLUE')
        </id>
        <category term="NAV.Location"
            scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
        <link rel="edit" title="Location"
            href="Company('CRONUS%20International%20Ltd.')/Location('BLUE')" />
        <title />
        <updated>2018-01-09T05:55:24Z</updated>
        <author>
            <name />
        </author>
        <content type="application/xml">
            <m:properties>
                <d:Code>BLUE</d:Code>
                <d:Name>Blue Warehouse</d:Name>
                <d:ETag>28;DgAAAAJ7/0IATABVAEUAAAAAAA==6;1604150;</d:ETag>
            </m:properties>
        </content>
    </entry>
</ml_root>

I tried to convert it using the following XSLT.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output encoding="UTF-8" method="xml" indent="yes"/>

   <xsl:template match="/">
      <ROWS>
         <COMPANY_SITE_TAB>
            <xsl:for-each select="ml_root/entry/content/properties">
            <ROW>
               <COMPANY>TCO</COMPANY>
               <CONTRACT><xsl:value-of select="Code"/></CONTRACT>
               <COUNTRY>UNITED KINGDOM</COUNTRY>
               <DESCRIPTION><xsl:value-of select="Name"/></DESCRIPTION>
            </ROW>
            </xsl:for-each>
         </COMPANY_SITE_TAB>
      </ROWS>
   </xsl:template>
</xsl:stylesheet>

But it gives only the following output.

<ROWS>
   <COMPANY_SITE_TAB/>
</ROWS>

Can you please help me to understand the error.


Solution

  • If you check the input XML carefully there are multiple namespaces (attributes starting with xmlns) associated with the elements in the XML. Since these namespaces are not mapped in the XSLT, the output XML does not show any data.

    For the output XML, the elements from which data is being accessed belong to following namespaces

    xmlns="http://www.w3.org/2005/Atom"
    xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
    xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
    

    We need to map these namespaces in the XSLT as well and the namespaces are not required in the output, we use the exclude-result-prefixes.

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
        xmlns:a="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
        xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
        exclude-result-prefixes="a d m">
    

    The template needs to be modified to access elements according to the namespaces they belong to.

    <xsl:for-each select="ml_root/a:entry/a:content/m:properties">
    

    and

    <xsl:value-of select="d:Code"/>
    <xsl:value-of select="d:Name"/>
    

    Below is the complete XSLT.

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
        xmlns:a="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices"
        xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
        exclude-result-prefixes="a d m">
    
        <xsl:output method="xml" indent="yes" />
        <xsl:strip-space elements="*" />
    
       <xsl:template match="/">
          <ROWS>
             <COMPANY_SITE_TAB>
                <xsl:for-each select="ml_root/a:entry/a:content/m:properties">
                <ROW>
                   <COMPANY>TCO</COMPANY>
                   <CONTRACT><xsl:value-of select="d:Code"/></CONTRACT>
                   <COUNTRY>UNITED KINGDOM</COUNTRY>
                   <DESCRIPTION><xsl:value-of select="d:Name"/></DESCRIPTION>
                </ROW>
                </xsl:for-each>
             </COMPANY_SITE_TAB>
          </ROWS>
       </xsl:template>
    </xsl:stylesheet>
    

    Following is the output.

    <ROWS>
        <COMPANY_SITE_TAB>
            <ROW>
                <COMPANY>TCO</COMPANY>
                <CONTRACT>BLUE</CONTRACT>
                <COUNTRY>UNITED KINGDOM</COUNTRY>
                <DESCRIPTION>Blue Warehouse</DESCRIPTION>
            </ROW>
        </COMPANY_SITE_TAB>
    </ROWS>