ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Marge separate XML Chunks in SQLRPG

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Marge separate XML Chunks in SQLRPG

    I am experimenting with using XMLELEMENT, XMLFOREST, and XMLSERIALIZE to build XML in SQLRPGLE

    What I would like to do, is instead of having one huge monolithic SQL Statement, is build the XML in chunks stored in host variables, and stitch them together later

    But I cannot work out how to add one chunk of XML into another For example:

    Code:
    // var1 host var is a varchar containing: 'ABCD';
    // var2 host var contains pre-built XML in whatever data type would make this work: '<var2subtag>DEFG</var2subtag>'
    
    
    xmlforest(:var1 as "somename",
              :var2 as "subXML")
    
    
    // Desired outcome (indented for legibility):
    //
    // <somename>ABCD</somename>
    // <subXML>
    //   <var2subtag>DEFG</var2subtag>
    // </subXML>
    //
    If :var2 is a char data type, it is parsed as a plain string, not as XML:
    Code:
    // <somename>ABCD</somename>
    // <subXML>&gt;var2subtag&lt;DEFG&gt;/var2subtag&lt;</subXML>
    I cannot see a way of telling XMLFOREST/XMLELEMENT that this is parsed XML to append, rather than a regular string


    Is there a way to accomplish what I want to accomplish?

  • #2
    Sorry, the title should be "Merge", not "Marge")

    I worked it out - I defined var2 as SQLTYPE(CLOB 10000), and included it in the values list for XMLELEMENT instead of XMLFOREST

    My stumbling block was that my actual chunk (fragment?) had multiple root nodes, which does not seem to work for a fragment

    I'll do a more detailed writeup when I have more time.

    Comment


    • #3
      So what I did was:

      Code:
      dcl-s xmlInner   sqltype(XML_CLOB:10000) ccsid(1208);
      dcl-s xml        sqltype(XML_CLOB:10000) ccsid(1208);
      
      // Create inner fragment
             exec sql
               set :xmlInner =
                   xmlelement(NAME "innerTag",
                     xmlforest(
                       :valI1 as "inner1", 
                       :valI2 as "inner2"
                     ) );      
      
      
      // Create full XML, appending the inner fragment
             exec sql
               set :xml = xmldocument(
                 xmlelement(NAME "testXML",
                   xmlforest(
                     :val1 as "value1", 
                     :val2 as "value2"),
                   :xmlInner
                 ));  
      
      // result 
      <testXML>
        <value1>somevalue1</value1>
        <value2>somevalue2</value2>
        <innerTag>
          <inner1>someinnervalue1</inner1>
          <inner2>someinnervalue2</inner2>
        </innerTag>
      </testXML>

      I do have some followup questions:

      What I want to be able to do is output a DS array of unknown length to XML. Right now the only way I can think of to do this that worked without resorting to manual string manipulation is to output the array to a temporary table, and build the XML directly from that table.

      Is there a way I could have an XML_CLOB containing:
      Code:
      <rootTag>
        <elemTag>value</elemTag>
      </rootTag>
      And then append additional instances of <elemTag> to the <rootTag> so I get:
      Code:
      <rootTag>
        <elemTag>value</elemTag>
        <elemTag>value</elemTag>
        <elemTag>value</elemTag>
      </rootTag>
      I can't find a way to do that

      Or, is there a way I could have an XML_CLOB containing:
      Code:
        <elemTag>value</elemTag>
      And then concatenate additional instances of <elemTag> so I get:
      Code:
        <elemTag>value</elemTag>
        <elemTag>value</elemTag>
        <elemTag>value</elemTag>
      And then append all of these to a new instance of <rootTag> even though the XML_CLOB has multiple root nodes so I get:
      Code:
      <rootTag>
        <elemTag>value</elemTag>
        <elemTag>value</elemTag>
        <elemTag>value</elemTag>
      </rootTag>
      Everything I have tried has failed because XMLELEMENT and XMLFOREST will not append an CML_CLOB that contains multiple root ndoes

      I could do it with string manipulation - using XMLELEMENT to output and append each <elemTag> to a string, then manually append <rootTag> and </rootTag> strings to either end, and then XMLPARSE that back to XML_CLOB, but I would prefer a solution where all XML tags are created with the XML SQL functions

      Comment


      • Vectorspace
        Vectorspace commented
        Editing a comment
        And to make it a bit worse, you cannot create a fragment where you are using namespace naming unless the fragment also contains that namespace definition. So if every tag in the XML uses the namespace and the namespace is only defined in the XML header, then you cannot create fragments.
    Working...
    X