Home > Blockchain >  In an XML with 2 or more namespace declaration, is it possible to reference to xpaths dynamically if
In an XML with 2 or more namespace declaration, is it possible to reference to xpaths dynamically if

Time:07-06

I'm working on some xsl development. The XML being transformed has 2 namespaces. One has a prefix of ns2 xmlns:ns2="http://xmlns.example.com/eventNotify/v1".

The other, is the default : xmlns="http://xmlns.example.com/cds/customer"

Suppose we have this xml that has 2 namespaces

<?xml version="1.0" encoding="UTF-8"?>
<ns2:accountEventNotify xmlns:ns2="http://xmlns.example.com/eventNotify/v1" xmlns="http://xmlns.example.com/cds/customer" schemaVersion="1">
   <ns2:header>
      <ns2:employee>
         <ns2:opco>ABCD</ns2:opco>
         <ns2:number>1111111</ns2:number>
      </ns2:employee>
      <ns2:sourceSystem>SYS1</ns2:sourceSystem>
      <ns2:msgCreateTime>2022-06-15T16:58:30.599Z</ns2:msgCreateTime>
      <ns2:businessEvent>
         <ns2:event>maintenance</ns2:event>
      </ns2:businessEvent>
   </ns2:header>
   <ns2:accountNumber>123456789</ns2:accountNumber>
   <ns2:messageType>CREATE</ns2:messageType>
   <ns2:create>
      <enterpriseProfile domain="customer" majorVersion="0" minorVersion="30">
         <accountNumber>123456789</accountNumber>
         <profile>
            <customerType>AAA</customerType>
            <accountType>AAA</accountType>
            <accountStatus>
               <statusCode>ACTIVE</statusCode>
               <statusDate>2022-06-15</statusDate>
            </accountStatus>
            <creationDate>2022-06-15</creationDate>
            <originSource>FF</originSource>
            <accountLinkageFlag>false</accountLinkageFlag>
            <welcomeKit>
               <welcomeKitFlag>false</welcomeKitFlag>
            </welcomeKit>
         </profile>
      </enterpriseProfile>     
   </ns2:create>
</ns2:accountEventNotify>

For example, if I want to exclude the parent node <ns2:create> and its child nodes, I can simply write <xsl:template match="ns2:create" /> which is fine.

There are two possible future scenarios in the system I'm working on :

  1. What if the ns2 prefix somehow changed to abc or something else?

    That scenario will break reference(s) to existing xpath(s) in xsl file. Example is <xsl:template match="ns2:create" /> must change to <xsl:template match="abc:create" />

  2. What if namespace value got change inversely / opposite?

    FROM :

    <?xml version="1.0" encoding="UTF-8"?> <ns2:accountEventNotify xmlns:ns2="http://xmlns.example.com/eventNotify/v1" xmlns="http://xmlns.example.com/cds/customer" schemaVersion="1">

    TO :

    <?xml version="1.0" encoding="UTF-8"?> <ns2:accountEventNotify xmlns:ns2="http://xmlns.example.com/cds/customer" xmlns="http://xmlns.example.com/eventNotify/v1" schemaVersion="1">

My worry is the possibility of the code breaking in the future. Currently, the source of the XML I am transforming is generating namespace values inconsistently (Like in scenario 2 above).

How to handle the 2 scenarios above? Should I write 2 separate XSL scripts? What if ns2 changes to abc in the future?

I'd appreciate any advice.

Thank you.

CodePudding user response:

Let's assume you've defined a ns1 namespace prefix for the default namespace, for clarity of reference. Then here are two options:

  1. Match anticipated namespaces1:

    <xsl:template match="ns1:create | ns2:create" />
    
  2. Ignore namespaces:

    XSLT 1.0

    <xsl:template match="*[local-name() = 'create']" />
    

    XSLT 2.0

    <xsl:template match="*:create" />
    

Remember that changing namespaces is equivalent to changing names. Do not expect general robustness in the face of such changes. If create is changed to destroy, there's likely an associated semantic difference, and your code cannot be expected to deal with such changes without an update. Similarly, create in one namespace may have different semantics than create in a different namespace.


1. Thanks to @michael.hor257k for a simplifying suggestion for form #1.

CodePudding user response:

If you need to handle two variant vocabularies that differ primarily in the choice of namespace URI, then my preferred approach is to create a pipeline of two transformations: the first normalizes the namespace URI to the preferred form, and the second does the real work.

This gives you better separation of concerns, with simpler and more reusable code, and less chance of bugs through forgetting to handle both namespaces everywhere you use an element name.

  • Related