ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

XML-INTO issues please help!

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

  • XML-INTO issues please help!

    I am learning XML-INTO first time and am trying to convert using RPG free format. Since XML has multiple elements, please help me to fix this simple program

    When I run the following program I get "An XML parsing error was detected " error.

    This is actually EDI X12 data converted into XML so that I can populate database.

    **FREE
    dcl-c XML2 '<loop Id="N1">+
    <segment Id="N1">+
    <element Id="N101">ST</element>+
    <element Id="N102">ABC COMPANY</element>+
    <element Id="N103">9</element>+
    <element Id="N104">124575</element>+
    </segment>+
    </loop>+
    <segment Id="ITD">+
    <element Id="ITD01">01</element>+
    <element Id="ITD02">3</element>+
    <element Id="ITD03">2</element>+
    <element Id="ITD05">45</element>+
    <element Id="ITD06">20180415</element>+
    <element Id="ITD07">46</element>+
    </segment>+
    <segment Id="DTM">+
    <element Id="DTM01">011</element>+
    <element Id="DTM02">20180228</element>+
    </segment>+
    <loop Id="IT1">+
    <segment Id="IT1">+
    <element Id="IT101">1</element>+
    <element Id="IT102">72</element>+
    <element Id="IT103">EA</element>+
    <element Id="IT104">8.09</element>+
    <element Id="IT106">UP</element>+
    <element Id="IT107">054132408604</element>+
    <element Id="IT108">SK</element>+
    <element Id="IT109">125440</element>+
    <element Id="IT110">VC</element>+
    <element Id="IT111">641623</element>+
    </segment>+
    </loop>+
    <loop Id="IT1">+
    <segment Id="IT1">+
    <element Id="IT101">10</element>+
    <element Id="IT102">36</element>+
    <element Id="IT103">EA</element>+
    <element Id="IT104">8.09</element>+
    <element Id="IT106">UP</element>+
    <element Id="IT107">039938349219</element>+
    <element Id="IT108">SK</element>+
    <element Id="IT109">154510</element>+
    <element Id="IT110">VC</element>+
    <element Id="IT111">778634</element>+
    </segment>+
    </loop>';


    dcl-ds loop qualified dim(20);
    dcl-ds segment;
    Id char(4);
    dcl-ds element dim(50);
    Id char(4);
    data varchar(50);
    end-ds;
    end-ds;
    end-ds;

    xml-into loop %xml(XML2:'case=any datasubf=data allowmissing=yes');

    *inlr = *on;

    Thank you.

  • #2
    I have never used XML-INTO myself, but I have used several other types of XML SQL processing on iSeries. And in my experience, iSeries SQL only considers an XML document to be valid if it contains a single root node. i.e.:

    Code:
    <thisIsRootNode>
      <loop>
        ...
      </loop>
      <loop>
        ...
      </loop>
      <loop>
        ...
    ​​​​​​​  </loop>
    </thisIsRootNode>
    So you might want to try that - add an extra opening tag at the start and closing tag at the end so it only has a single root node when XML-INTO comes to process it. Note that means you will need an additional DS that contains loop, that XML-INTO can decode into.


    Additionally, your DS structure implies this XML structure:
    Code:
    loop (up to 20)
      segment
        element /element(up to 50)
     /segment
    /loop
    But that is not what your XML string has, it has segment tags that are not inside loop tags

    Comment


    • #3
      Your XML is invalid - which is what the parser is telling you. In future I suggest you copy/paste the XML into an editor that understands it. That's what I did with RDi and the answer was immediately obvious. A valid XML document must have a root element that encompasses all others - yours does not. I simply added an element I called <root> at the beginning and </root> at the very end. XML is now valid.

      <edited because I'm an idiot and need to wake up!>

      But your RPG needs help too. You need to count the number of elements so you will need to add countprefix=count_. Do yourself a favor and NEVER EVER use allowmissing=yes - certainly when there is an alternative such as I have shown here. It will bite you in the rear end. For example once you specify that the entire XML could be a different document and XML-INTO would say "OK". It just would never find any data or tell you you had a problem. If you want to understand this option better try this https://www.itjungle.com/2015/08/18/fhg081815-story01/

      Code:
      dcl-ds loop qualified dim(20);
         Id  char(4);  // <--- Need this added
         count_segment int(5); // And this
         dcl-ds segment dim(50);  // Don't know how many you need
            Id char(4);
            count_element  int(5);   // <--- count_ fields avoid use of allowmissing
            dcl-ds element dim(50);
                Id char(4);
                data varchar(50);
            end-ds;
         end-ds;
      end-ds;
      The XML-INTO and my test loop becomes:

      Code:
      xml-into loop %xml(XMLSource:
                         'path=root/loop case=any countprefix=count_ doc=file +
                            datasubf=data');
      
      Dsply ( ' Total of ' + %Char(elementCount) + ' elements loaded' );
      
      For i = 1 to elementCount;
         Dsply ( 'loop ' + %Char(i) + ' has ' +
                  %char(loop(i).count_segment) + ' segments' );
      endfor;
      This all appears to work perfectly with the adjustments to the XML mentioned earlier. including moving the segments into the loop.
      Last edited by JonBoy; May 3, 2018, 12:17 PM.

      Comment


      • #4
        HTML Code:
        **FREE
        dcl-ds transaction qualified;
          Control varchar(10);
          Name    varchar(10);
          DocType char(3);
          dcl-ds segment;
              Id char(3);
              dcl-ds element dim(10);
                  Id char(5);
                  data varchar(20);
              end-ds;
          end-ds;
          dcl-ds loop;
              Id char(3);
              dcl-ds segment;
                  Id char(3);
                  dcl-ds element dim(10);
                     Id char(5);
                     data varchar(20);
                  end-ds;
              end-ds;
          end-ds;
        end-ds;
        
        dcl-s loaded    int(10);
        dcl-s XMLsource varchar(500);
        dcl-s opt       varchar(200);
        XMLsource = '/edi/00234751.xml';
        opt = 'doc=file case=any allowmissing=yes allowextra=yes +
               path=ediroot/interchange/group/transaction datasubf=data';
        
        xml-into %Handler(myHandler : loaded) %xml(XMLSource : opt);
        
        Dsply ('Processed ' + %Char(loaded) + ' total elements ');
        
        *inlr = *on;
        
        dcl-proc myHandler; 
           dcl-pi *n int(10);
              loaded      int(10);
              tran        likeds(transaction) dim(5) const;
              count       int(10) value;
           end-pi;
        
           dcl-s  x       int(10) inz;
        
         //for x = 1 to count;
         //    dsply tran(x).segment;
         //endfor;
           loaded += count;
           dsply (%char(count) + ' loaded on this call');
           return 0;
        end-proc myHandler;
        Attached Files

        Comment


        • #5
          This version seems to work. Basically I think I just added a couple of Dims (marked). I suggest that you add a countprefix and add the counts for loop and segment that may avoid the need for allowmissing=yes but even if you leave that in it will make it easier to control looping through the data..

          Code:
          **FREE
          ctl-opt DftActGrp(*No);
          
          dcl-ds transaction_T  Template qualified;
            Control varchar(10);
            Name    varchar(10);
            DocType char(3);
            dcl-ds segment Dim(10);   // Needs a Dim
                Id char(3);
                dcl-ds element dim(10);
                    Id char(5);
                    data varchar(20);
                end-ds;
            end-ds;
            dcl-ds loop  Dim(10);  // Needs Dim
                Id char(3);
                dcl-ds segment;
                    Id char(3);
                    dcl-ds element dim(10);
                       Id char(5);
                       data varchar(20);
                    end-ds;
                end-ds;
            end-ds;
          end-ds;
          
          
          dcl-s loaded    int(10);
          dcl-s XMLsource varchar(500);
          dcl-s opt       varchar(200);
          
          XMLsource = '/home/paris/xmlstuff/Raymonds.xml';
          opt = 'doc=file case=any allowmissing=yes allowextra=yes +
                 path=ediroot/interchange/group/transaction datasubf=data';
          
          xml-into %Handler(myHandler : loaded) %xml(XMLSource : opt);
          
          Dsply ('Processed ' + %Char(loaded) + ' total elements ');
          
          *inlr = *on;
          
          
          dcl-proc myHandler;
             dcl-pi *n int(10);
                loaded      int(10);
                tran        likeds(transaction_T) dim(5) const;
                count       int(10) value;
             end-pi;
          
             dcl-s  x       int(10) inz;
          
             loaded += count;
             dsply (%char(count) + ' loaded on this call');
             return 0;
          
          end-proc myHandler;

          Comment


          • #6
            Thanks Jon, I changed the code per your advise and the result is the same as before.

            DSPLY 1 loaded on this call
            DSPLY Processed 1 total elements

            However, I have several elements. Can you please check the code and run in your system and see you get the same results?

            Thank you once again.

            Comment


            • #7
              I just modified the data you supplied (which only had one transaction) to add additional transactions by adding this code after the first transaction.
              Code:
              <transaction DocType="810" Name="Invoice" Control="14230001">
                 <segment Id="BIG">
                     <element Id="BIG01">20190522</element>
                     <element Id="BIG02">10695657</element>
                     <element Id="BIG04">80903</element>
                 </segment>
                 <segment Id="RAREF">
                     <element Id="REF01">IA</element>
                     <element Id="REF02">001948520</element>
                 </segment>
                 <loop Id="N1">
                     <segment Id="N1">
                        <element Id="N101">ST</element>
                        <element Id="N102">RECEIVING COMPANY</element>
                        <element Id="N103">93</element>
                        <element Id="N104">01</element>
                     </segment>
                  </loop>
               </transaction>
              The result is that the hander reports receiving 3 transactions (correct) and the data all appears to be in place.

              I suggest you try copy/pasting my code and seeing what happens. Byond that I can only suggest that you check and see if you have missing PTFs or something because it seems to be working fine for me on my 7.3 system.

              Comment


              • #8
                Awesome. I didn't change my code completely and it's now working. I am on 7.3 as well with all PTFs applied two weeks ago. Thank you very much. As I mentioned last year for some reason XML-INTO didn't work instead I coded XML-SAX and with cross reference file I was able to achieve more efficiently since EDI X12 has different layouts and elements for transaction types 810, 850, 856, 997, etc.

                I dealt with Scott Klement a long time, convey my regards to him.

                Comment


                • #9
                  Glad it works for you.

                  Comment

                  Working...
                  X