Clarity

  • 1.  GEL - Loop to build XML

    Posted Jan 06, 2017 06:24 PM

    Hello guru's, I have worked very hard on this today... but I am still having some issues trying to get this to work. I can't seem to figure out how to do the loop and store the variables into the xml write. I can totally do this from a query, but for some reason, I can't figure it out yet on the xml read. It only does just the one row and not all three. Ugh.

    1. did the read

    2. stored the data

    3. now i need to loop through and save the data into the segments.

       ie. 

    <HardAllocCurve>
         <segment finish="2016-12-25T00:00:00" rate="1.0" start="2016-10-02T08:00:00"/>
         <segment finish="2016-12-30T00:00:00" rate="1.0" start="2016-12-27T00:00:00"/>
         <segment finish="2017-09-29T00:00:00" rate="1.0" start="2017-01-02T00:00:00"/>
    </HardAllocCurve>

    part of the code that i need help with. 

    <!-- loop over the segments node and pull the start,finish and rate--> 
    <gel:forEach var="segments" select="$result/soapenv:Envelope/soapenv:Body/NikuDataBus/requisitions/requisition/requisitionResource/requestCurve/segment"> 
         <gel:set asString="true" select="$segments/@finish" var="segfinish"/>
         <gel:set asString="true" select="$segments/@start" var="segstart"/>
         <gel:set asString="true" select="$segments/@rate" var="segrate"/>
         <gel:log level="SEGMENTS" category="DEBUG" message="start=${segfinish}, finish=${segfinish}, rate=${segrate}"/>

         <gel:parse var="hardXML">
              <HardAllocCurve>
                   <segment finish="${segfinish}" rate="${segrate}" start="${segstart}"/>     
              </HardAllocCurve>
         </gel:parse>
         
         <gel:include select="$hardXML"/>
         
    </gel:forEach> 
    <!-- print out the hardXML results -->
    <gel:log level="Info">
         <gel:expr select="$hardXML/"/>
    </gel:log>

    it is at least displaying them,

    but only the first row in the HardAllocCurve/segment node.

    So, the xml file becomes this, when the rest of the code is run:

    And i need it to have all three segments.

     

    Please someone help, I am going crazy.Does anyone have any suggestions I can try or please point me in a direction. I have read the numerous posts on this in the community, and i have to say... it's gotten me this far!! 

     

    Thank you for any help provided.

     

    Keri



  • 2.  Re: GEL - Loop to build XML

    Posted Jan 07, 2017 05:00 AM

    You need your gel:parse outside of your foreach.

     

    i.e. something like

     

    <gel:parse var="hardXML">
    <gel:forEach var="segments" select="$result/soapenv:Envelope/soapenv:Body/NikuDataBus/requisitions/requisition/requisitionResource/requestCurve/segment"> 
         <gel:set asString="true" select="$segments/@finish" var="segfinish"/>
         <gel:set asString="true" select="$segments/@start" var="segstart"/>
         <gel:set asString="true" select="$segments/@rate" var="segrate"/>
         <gel:log level="SEGMENTS" category="DEBUG" message="start=${segfinish}, finish=${segfinish}, rate=${segrate}"/>

              <HardAllocCurve>
                   <segment finish="${segfinish}" rate="${segrate}" start="${segstart}"/>     
              </HardAllocCurve>
    </gel:forEach>      
    </gel:parse>
        


  • 3.  Re: GEL - Loop to build XML

    Posted Jan 10, 2017 02:02 PM

    Thank you Dave_3.0 , I am still having some trouble with the script, but I think I know what the issue is...more testing :-)

    Keri


  • 4.  Re: GEL - Loop to build XML

    Posted Jan 10, 2017 03:03 PM

    Like this:

     

    <?xml version="1.0" encoding="utf-8"?>
    <gel:script xmlns:core="jelly:core"
         xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary"
         xmlns:sql="jelly:sql"
         xmlns:util="jelly:util"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

         
         <core:set var="dummy" value="3,2,4,20,5,6,7,1" />
         <core:set var="dummyArray" value='${dummy.split(",")}' />

         <gel:parse var="hardXML">
              <HardAllocCurve>
              </HardAllocCurve>
         </gel:parse>

         <core:forEach items="${dummyArray}" var="index">

         <gel:log>index = ${index}</gel:log>

         <gel:parse var="segment">
              <segment finish="${index}" rate="${index}" start="${index}"/>   
         </gel:parse>
         <gel:set var="segmentNode" select="$segment/segment"/>
         
         <gel:set value="${segmentNode}" select="$hardXML/HardAllocCurve" insert='true'/>
         
    </core:forEach>

         <gel:serialize fileName="hardXML.xml" var="${hardXML}"/>
    <gel:log level="Info">
         <gel:expr select="$hardXML/"/>
    </gel:log>

    </gel:script>

     

     

     

    V/r,

    Gene



  • 5.  Re: GEL - Loop to build XML

    Posted Jan 11, 2017 03:58 AM

    Ok just a comment here, that might clarify some confusion (or might not, who knows!).

     

    AFAIK there are two ways of building up a XML "thing" within a GEL script - for the sake of argument I'm going to call these two ways "inline" and "xpath" (whether these terms are strictly right, I don't know!).

     

    I use the "inline" method, only because that was the first way that I encountered so I am just used to it - the code Gene posted is the "xpath" method - I suspect that the "xpath" way is the right/better way to do things, but a lot of examples on these discussion boards (including anything that I've ever posted) probably uses the "inline" method.

     

    How the two methods differ I'll try to explain in pseudo-code - example of building an XML based on some query results;

     

    --

     

    "Inline" - the XML is built up inline in the GEL script and the code goes something like this;

     

    Open a XML document ( this is the start of the gel:parse tag)

    Write some XML header information to the document - do this just by including the XML text inline into the GEL script

    Open a query on the database;

    Start to loop around the results from the query 

    each result line from the query write a record to the XML document - again just include the relevant text inline in the GEL

    Finish loop

    Close the XML document (this is the end of the gel:parse tag)

     

    --

     

    "Xpath" - we create a XML document and use xpath to add things to it;

     

    Create (i.e. open and close) an empty, but fully formed XML document (this is the whole 'open' gel:parse and close 'gel:parse')

    use Xpath syntax to write some data to the XML document

    Open a query on the database;

    Start to loop around the results from the query 

    each result line from the query use Xpath syntax to insert the data to the XML document

    Finish loop

     

    --

     

    I guess the personal differences might just come down to what you are familiar with ; in the "inline" way we have to make sure that the XML/XOG syntax that we are putting inline into the GEL script is syntactically correct (from an XML/XOG point of view), with the "xpath" way we don't have to worry so much about the XML syntax (since XPath/XML just takes care of that) but the xpath syntax itself I find can be a bit hard to get right.

     

    (@Keri - so the 'solution' that I gave to your loop question was very much an "inline" way of doing things, Gene's posted solution is the "xpath" way)

     

    YMMV...



  • 6.  Re: GEL - Loop to build XML

    Posted Jan 11, 2017 08:04 AM

    Nice explanation Dave!

     

    As for the right method, you will most likely find that the inline method is the most common.  The xpath method can only produce a xml document but the inline method isn’t limited to a xml document.

     

    The inline method is based on XML pipelines.  The idea in an XML pipeline is for XML events to be created by some generator (PPM Gel Scripts) and then flow through multiple filters, transformers or processors to some ultimate output.  It should be noted that highly complex, yet easy to use XML pipelines can be created since the pipelines don't have to be linear.  ref: http://commons.apache.org/proper/commons-jelly/pipeline.html

     

    If you ever get the chance to work on other platforms e.g. Service-Now, JIRA… (each is moving away from Jelly), you will get very familiar with pipelining.

     

    V/r,

    Gene



  • 7.  Re: GEL - Loop to build XML

    Posted Jan 11, 2017 08:52 AM

    Ha - "inline" always just seemed a bit "cludgey" to me, but now I know its a legitimate technique I shall pretend that I always knew what I was doing... 

     

    ....Hmmm "pipelines" yes thats it....



  • 8.  Re: GEL - Loop to build XML

    Posted Jan 20, 2017 05:15 PM

    I actually ended up doing it like this and it works perfectly. 

                        <!-- loop over the segments node and pull the start,finish and rate--> 
                        <gel:forEach var="segments" select="$result/soapenv:Envelope/soapenv:Body/NikuDataBus/requisitions/requisition/requisitionResource/requestCurve/segment"> 
                             <gel:set asString="true" select="$segments/@finish" var="segfinish"/>
                             <gel:set asString="true" select="$segments/@start" var="segstart"/>
                             <gel:set asString="true" select="$segments/@rate" var="segrate"/>
                             <gel:log level="SEGMENTS" category="DEBUG" message="start=${segfinish}, finish=${segfinish}, rate=${segrate}"/>

                             <gel:parse var="hardXML">
                                  <segment finish="${segfinish}" rate="${segrate}" start="${segstart}"/>     
                             </gel:parse>
                             <gel:set select="$projectXML//NikuDataBus/Projects/Project/Resources/Resource/HardAllocCurve" value="${hardXML}" insert="true"/>
                             <core:set value="${segmentCnt + 1}" var="segmentCnt"/>
                        </gel:forEach> 
                        <core:choose>
                             <core:when test="${segmentCnt > 0}">
                                  <gel:set asString="true" select="$result/soapenv:Envelope/soapenv:Body/NikuDataBus/XOGOutput/Statistics" var="XOGState"/>
                                            <core:choose>
                                                 <!-- Success -->
    ....
    ....

    Thank you for everyone's input!! :-)