[SOLVED] stylesheet to convert a xml source file to a xml target format whilst introducing prefixes to the target elements

Issue

I have this source xml

<?xml version="1.0" encoding="UTF-8" ?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <StartOfTransmission>
        <SenderId>SENDERSID</SenderId>
        <ReceiverId>RECEIVERSID</ReceiverId>
        <TRANSDATE>13-09-2010</TRANSDATE>
        <TRANSTIME>12:00:00</TRANSTIME>
        <SenderReference>1234</SenderReference>
        <ReceiverReference/>
        <ApplicationReference>ORDHDR</ApplicationReference>
    </StartOfTransmission>
</Document>

and I would like to convert it to this format using a stylesheet transformation. (please note the a: and xmlns: prefixes are required.)

<?xml version="1.0" encoding="UTF-8"?>
<a:Document xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://127.0.0.1:8080 http://127.0.0.1:8080/test/tbattributesxml2.xsd"
          xmlns:a="http://127.0.0.1:8080">
    <a:StartOfTransmission SenderId="SENDERSID" ReceiverId="RECEIVERSID" transdatetime="2010-09-13T12:00:00.000" SenderReference="1234" ReceiverReference="" ApplicationReference="ORDHDR"/>
</a:Document>

Once it is converted correctly the target xml will pass this xsd validation below.

<xs:schema  attributeFormDefault="unqualified"
            elementFormDefault="qualified"
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://127.0.0.1:8080"
            xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
            xmlns:w="http://127.0.0.1:8080"
            vc:minVersion="1.1" >
  
  <xs:element name="Document">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="w:StartOfTransmission" minOccurs="1" maxOccurs="1"/>    
      </xs:sequence> 
    </xs:complexType>
  </xs:element>
  
  <xs:element name="StartOfTransmission">
      <xs:complexType>

      <xs:attribute name="SenderId" use="required">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:minLength value="1"/>
            <xs:maxLength value="14"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>

      <xs:attribute name="ReceiverId" use="required">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:minLength value="1"/>
            <xs:maxLength value="14"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>

      <xs:attribute name="transdatetime" use="required" type="xs:dateTime"/>

      <xs:attribute name="SenderReference" use="required">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:minLength value="1"/>
            <xs:maxLength value="14"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>

      <xs:attribute name="ReceiverReference" use="optional">
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:minLength value="0"/>
            <xs:maxLength value="14"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>

      <xs:attribute name="ApplicationReference" use="required">
        <xs:annotation>
          <xs:documentation>Value = ORDHDR</xs:documentation>
        </xs:annotation>
        <xs:simpleType>
          <xs:restriction base="xs:string">
            <xs:enumeration value="ORDHDR"/>
            <xs:minLength value="1"/>
            <xs:maxLength value="14"/>
          </xs:restriction>
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>
  
</xs:schema>

I have started this stylesheet below which half works (except the colons are missing). When i try to introduce the a: and xmlns: tags it breaks. And I can’t get the ‘xmlns:xsd="http://www.w3.org/2001/XMLSchema"’ to appear as the first attribute in the Document element. As always, any help gratefully received.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:saxon="http://saxon.sf.net/"
    xmlns:a="http://127.0.0.1:8080"
    exclude-result-prefixes="xs"
    version="2.0" >
    
    <xsl:output method="xml" indent="no" />
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="/">
        <xsl:text>&#xA;</xsl:text>
        <xsl:apply-templates mode="copy" select="."/>        
    </xsl:template>
    
    <xsl:template match="*|text()" mode="copy">
        <xsl:copy>
            <xsl:apply-templates mode="copy"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="Document" mode="copy" name="a" >
        <xsl:copy>
            <xsl:attribute name="{'xmlnsxsd'}"><xsl:value-of select="'http://www.w3.org/2001/XMLSchema'"/></xsl:attribute>
            <xsl:attribute name="{'xsi:schemaLocation'}"><xsl:value-of select="'http://127.0.0.1:8080 http://127.0.0.1:8080/tbattributesxml2.xsd'"/></xsl:attribute>
            <xsl:attribute name="{'xmlnsa'}"><xsl:value-of select="'http://127.0.0.1:8080'"/></xsl:attribute>
            <xsl:apply-templates mode="copy"/>
        </xsl:copy>
    </xsl:template>
    
    
    <xsl:template match="StartOfTransmission" mode="copy">  
        <xsl:text>&#xA;&#x9;</xsl:text>
        <xsl:copy>
            
            <xsl:apply-templates mode="convert-to-attr" select="SenderId"/> 
            <xsl:apply-templates mode="convert-to-attr" select="ReceiverId"/>
            <xsl:variable name="dte" as="xs:string">
            <xsl:value-of select="concat(substring(TRANSDATE, 7, 4), '-', substring(TRANSDATE, 4, 2), '-', substring(TRANSDATE, 1, 2))"/>
            </xsl:variable>
            <xsl:variable name="tme" as="xs:string" select="TRANSTIME"/>
            <xsl:variable name="dateTime" select="concat($dte,'T',$tme,'.000')"/>
            <xsl:attribute name="transdatetime"><xsl:value-of select="$dateTime"/></xsl:attribute> 
            <xsl:apply-templates mode="convert-to-attr" select="SenderReference"/>
            <xsl:apply-templates mode="convert-to-attr" select="ReceiverReference"/>
            <xsl:apply-templates mode="convert-to-attr" select="ApplicationReference"/>

        </xsl:copy>
        <xsl:text>&#xA;</xsl:text>
    </xsl:template>


    <xsl:template match="*" mode="convert-to-attr">
        <xsl:attribute name="{name()}" select="text()"/>
    </xsl:template>
</xsl:stylesheet>

Solution

AFAICT, all you need to do is:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:a="http://127.0.0.1:8080">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/Document">
    <a:Document xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://127.0.0.1:8080 http://127.0.0.1:8080/test/tbattributesxml2.xsd">
        <xsl:apply-templates/>
    </a:Document>
</xsl:template>     

<xsl:template match="StartOfTransmission">
    <a:StartOfTransmission transdatetime="{replace(TRANSDATE, '(.{2})-(.{2})-(.{4})', '$3-$2-$1')}T{TRANSTIME}">
        <xsl:apply-templates select="* except(TRANSDATE, TRANSTIME)"/>
    </a:StartOfTransmission>
</xsl:template> 
    
<xsl:template match="StartOfTransmission/*">
    <xsl:attribute name="{name()}" select="."/>
</xsl:template>     
    
</xsl:stylesheet>

Note that this assumes TRANSDATE is in DD-MM-YYYY format (i.e. has a leading zero for day where needed).

Answered By – michael.hor257k

Answer Checked By – Pedro (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published.