piuser
piuser

Reputation: 51

Need help in aligning attribute value in rootnode using xslt

Thanks so much stackoverflow for your suggestions and answers.

below is my source code

<?xml version="1.0" encoding="UTF-8"?>
<PurchaseOrderDocument creationDate="2017-09-26T18:37:48.837Z" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
      xmlns:dssuid="urn:autoid:specification:universal:Identifier:xml:schema:1" 
      xmlns:dsscore="urn:autoid:specification:interchange:PMLCore:xml:schema:1">
    <PurchaseQuery>
        <EventDate>20170926</EventDate>
        <bizLocation>
            <id>urn:ddd:id:sgln:0315563.00000.0</id>
        </bizLocation>
        <Serialization>
            <BATCH_ID>3091145AB</BATCH_ID>
            <EXPIRATION_DATE>20190504</EXPIRATION_DATE>
            <PRODUCTION_DATE>20170505</PRODUCTION_DATE>
            <GTIN>04028691544401</GTIN>
            <Count>8088</Count>
        </Serialization>
    </PurchaseQuery>
</PurchaseOrderDocument>

This source xml has has unwanted namespaces My actual target should look like below

<?xml version="1.0" encoding="UTF-8"?>
<ns0:PurchaseOrderDocument xmlns:ns0="urn:global:mns:PurchaseOrder" 
                           creationDate="2017-09-26T18:37:48.837Z">
  <PurchaseQuery>
    <EventDate>20170926</EventDate>
    <bizLocation>
      <id>urn:ddd:id:sgln:0315563.00000.0</id>
    </bizLocation>
    <Serialization>
      <BATCH_ID>3091145AB</BATCH_ID>
      <EXPIRATION_DATE>20190504</EXPIRATION_DATE>
      <PRODUCTION_DATE>20170505</PRODUCTION_DATE>
      <GTIN>04028691544401</GTIN>
      <Count>8088</Count>
    </Serialization>
  </PurchaseQuery>
</ns0:PurchaseOrderDocument>

I tried applying the below XSLT , but attribute is not in the order the target is expecting

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

    <xsl:template match="@*|node()">

        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*" priority="1">

        <xsl:element name="{local-name()}" >
            <xsl:namespace name="ns0" 
                           select="'urn:global:mns:PurchaseOrder'"/> 
            <xsl:apply-templates select="@*|node()"/>

        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

The output after Applying XSLT is as below

<?xml version='1.0' encoding='UTF-8' ?>
<PurchaseOrderDocument xmlns:ns0="urn:global:mns:PurchaseOrder" 
                       creationDate="2017-09-26T18:37:48.837Z">
  <PurchaseQuery>
    <EventDate>20170926</EventDate>
    <bizLocation>
      <id>urn:ddd:id:sgln:0315563.00000.0</id>
    </bizLocation>
    <Serialization>
      <BATCH_ID>3091145AB</BATCH_ID>
      <EXPIRATION_DATE>20190504</EXPIRATION_DATE>
      <PRODUCTION_DATE>20170505</PRODUCTION_DATE>
      <GTIN>04028691544401</GTIN>
      <Count>8088</Count>
    </Serialization>
  </PurchaseQuery>
</PurchaseOrderDocument>

I tried many ways to get attribute Creation date before the namespace but went in vain .I am not able understand where I am missing.I have seen many blogs but unfortunately i am unable to find how to retain attribute(which is the dynamic value) in the root node to come in the correct position as in the target structure.This logic is bit important to me.Please suggest what should I include in the XSLT code so as to get the actual target structure.Any Help would be greatly appreciated.

Upvotes: 0

Views: 36

Answers (1)

Michael Kay
Michael Kay

Reputation: 163262

The order of attributes in serialized XML (and for this purpose, namespace declarations count as attributes) is considered to be of no significance, and cannot be controlled using XSLT. The same is true of most other serialization libraries that I know of.

Saxon does have an extension (xsl:output/@saxon:attribute-order) to control the order of non-namespace attributes, but it doesn't affect where namespace declarations appear relative to attributes.

I have to ask why this matters so much. If you are reading the XML using a conformant parser then it won't care what order the attributes appear in, and if you are reading the XML without using a conformant parser then you are making a bad mistake.

And also please help me how I can add prefix ns0: for each target line.

That's quite another matter. But you shouldn't be thinking "how can I add a prefix", you should be thinking "how can I put my output elements into namespace urn:global:mns:PurchaseOrder". Well, there are three ways of creating output elements:

  • xsl:copy will always create an element with the same name (namespace URI plus local name) as the original, so it's not suitable here.

  • literal result elements create an element with the same name (namespace URI plus local name) as the instruction in the stylesheet

  • xsl:element has two attributes, name and namespace, that allow you to control the two parts of the output element's name.

Upvotes: 1

Related Questions