xmlxslttransformabapabap-st

Run simple transformation against XML with dynamic namespaces?


I receive XML messages from a subsystem that sends changing namespaces. The system seems to increase a counter on a namespace depending on if its needed. I don't know how to handle this in SAP.

For example it might send me this:

<?xml version="1.0"?>
<topTag xmlns:ns1="xsd/namespacesForBoxes" 
        xmlns:ns2="xsd/namespacesForCartons" 
        xmlns:ns3="xsd/namespacesForPallets">

  <ns1:container>
    <ns1content/>
  </ns1:container>

  <ns2:container>
    <ns2:content/>
  </ns2:container>

  <ns3:container>
    <ns3:content/>
  </ns3:container>

</topTag>

which would be fine so far, but if the second element is not needed it would set the counter for pallets to 2, like so:

<?xml version="1.0"?>
<topTag xmlns:ns1="xsd/namespacesForBoxes" 
        xmlns:ns2="xsd/namespacesForPallets">

  <ns1:container>
    <ns1content/>
  </ns1:container>

  <ns2:container>
    <ns2:content/>
  </ns2:container>

</topTag>

Of course the <content> tag would hold different values depending on the namespace on my side, so the transformation will fail as it "hardcodes" the expected namespace.

Is there a way to implement this in simple transformations? The structure is quite big, so dynamic transformation via code is not feasible. Or is there a way to do this with other transformation technices?

Followup question: Is this normal? To me this seems like a very wild thing to implement, if namespaces are not needed they should not switch names. This just makes it horribly difficult to trace data back to the string.


Solution

  • As Siebe Jongebloed already pointed out, consumers of XML documents should never work with the namespace prefixes (like ns1) but work instead with the namespace URIs (like xsd/namespacesForBoxes).

    Simple transformations follow this rule and compare the namespace URI, not the prefix, as demonstrated by the following example:

    <?sap.transform simple?>
    <tt:transform xmlns:tt="http://www.sap.com/transformation-templates"
     xmlns:ddic="http://www.sap.com/abapxml/types/dictionary"
     xmlns:ns1="namespace_uri">
     <tt:root name="ROOT" type="ddic:SCARR"/>
     <tt:template>
      <ns1:Airline>
       <tt:value ref=".ROOT.CARRID"/>
      </ns1:Airline>
     </tt:template>
    </tt:transform>
    

    When you use this simple transformation to transform ABAP into XML, you get the namespace prefix ns1. But you can exchange the namespace prefix in the XML document and still use the same simple transformation to transform the XML back into ABAP:

    data: scarr     type scarr,
          xmlstring type string.
    scarr-carrid = 'XX'.
    call transformation ...
     source root = scarr
     result xml xmlstring.
    write / xmlstring.
    replace all occurrences of 'ns1' in xmlstring with 'ns2'.
    call transformation ...
     source xml xmlstring
     result root = scarr.
    write / scarr-carrid.