Clarity

Expand all | Collapse all

Gel Script to modify XOG output

Senthil Kumar Lakshmanan

Senthil Kumar LakshmananMay 16, 2016 12:01 PM

  • 1.  Gel Script to modify XOG output

    Posted Oct 26, 2012 05:14 PM
    So here's what I'm trying to do. I want to read out an object in Clarity using XOG, modify one of the values in that XOG and then push it back into clarity.
    I'm attempting to accomplish this with GEL and a process inside Clarity.
    <gel:script 
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xog="http://www.niku.com/xog" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:core="jelly:core" 
    xmlns:sql="jelly:sql" 
    xmlns:soap="jelly:com.niku.union.gel.SOAPTagLibrary" 
    xmlns:util="jelly:util" 
    xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary"
    xmlns:mail="jelly:email">
      
      <!-- XOG PARAMETERS -->
      <gel:parameter var="AppUser" default="admin" />
      <gel:parameter var="AppPass" default="xxxxxxx" secure="true" />
      <gel:parameter default="emails" var="Emails"/>
      <!-- CONNECTION STRING TO warmDB -->
      <!-- gel:setDataSource dbId="Niku" var="warmDB" / -->
      
           <!-- E-mail -->
        <core:set var="emailFrom" value="TestProcess" />
        <core:set var="emailServer" value="mail.server.com" />
    
      <!-- PREPARE SOAP BODY MESSAGE - READ COSTPLAN -->
      <gel:parse var="soapBody">
      <NikuDataBus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../xsd/nikuxog_read.xsd">
        <Header version="8.0" action="read" objectType="budgetPlan" externalSource="NIKU" />
        <Query>
          <Filter name="investmentID" criteria="EQUALS">BJ9</Filter>
          <Filter name="code" criteria="EQUALS">1102251200-BJ9a</Filter>
        </Query>
      </NikuDataBus>
      </gel:parse>
      
     <!-- INVOKE XOG -->
      <soap:invoke endpoint="http://nyt-warm6-at:82/niku/xog" var="xogResponse">
        <soap:message>
          <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xog="http://www.niku.com/xog">
            <soapenv:Header>
              <xog:Auth>
                <xog:Username>${AppUser}</xog:Username>
                <xog:Password>${AppPass}</xog:Password>
              </xog:Auth>
            </soapenv:Header>
            <soapenv:Body>
            
    <gel:include select="$soapBody" />
            </soapenv:Body>
          </soapenv:Envelope>
        </soap:message>
      </soap:invoke>
      <gel:set asString="true" select="$xogResponse" var="prxogResponse"/>
      
      <!-- PARSE XOG RESPONSE AND ASSIGN VARIABLES -->
      <!-- capture session id -->
      <gel:set select="$xogResponse/*/*/*/text()" asString="true" var="xogSessionID" />
     <gel:set select="$xogResponse" asString="true" var="xogTemp" />
     <util:replace new="1102251200-BJ9b" old="1102251200-BJ9a" value="${xogTemp}" var="xogTemp2"/> 
     <util:replace new="Archive Budget2" old="Archive Budget" value="${xogTemp2}" var="updatePlan"/>
    <gel:parse var="parsedUpdatePlan">${updatePlan}</gel:parse>
    <!-- INVOKE XOG -->
      <soap:invoke endpoint="http://nyt-warm6-at:82/niku/xog" var="xogUpdatePlan">
        <soap:message>
        
    <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xog="http://www.niku.com/xog">
                                    <soap-env:Header>
                                        <xog:Auth>
                                            <xog:SessionID>${xogSessionID}</xog:SessionID>
                                        </xog:Auth>
                                    </soap-env:Header>
                                    <soap-env:Body>
                                        <gel:include select="$parsedUpdatePlan"/>
                                    </soap-env:Body>
                                </soap-env:Envelope>
                            </soap:message>
      </soap:invoke>
      <!-- DESTROY XOG SESSION -->
      <soap:invoke endpoint="http://nyt-warm6-at:82/niku/xog" var="xogLogout">
        <soap:message>
          <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xog="http://www.niku.com/xog">
            <soapenv:Header><Auth><xog:SessionID>${xogSessionID}</xog:SessionID></Auth></soapenv:Header>
            <soapenv:Body><xog:Logout/></soapenv:Body>
          </soapenv:Envelope>
        </soap:message>
      </soap:invoke>
    <gel:set asString="true" select="$parsed" var="prparsed"/>
    
    <mail:email server="${emailServer}" from="${emailFrom}" to="${Emails}" subject="test process xog information">
    </mail:email>
    
      
    </gel:script>
    The above code throws an error
    null:59:35: <gel:parse> Reference is not allowed in prolog.
    when the process tries to run. I've also tried using the util:replace without first converting to a string, but when I try and convert the results to a string I get an error saying the XML is invalid.
    I cannot be the first person to try this but I wasn't able to find any other posts that specifically answered my use case.
    Anybody see what it is I'm missing?


  • 2.  RE: Gel Script to modify XOG output

    Posted Oct 26, 2012 06:33 PM

    Plidian wrote:

    null:59:35: <gel:parse> Reference is not allowed in prolog.
    ...
    I cannot be the first person to try this but I wasn't able to find any other posts that specifically answered my use case.
    Not connected to your use-case, but if you search for "prolog" you'll hit a couple of threads that have raised the same error message... :vader:

    Example : Multi Valued lookup Throwing System Error in CA Clarity R12 SP6

    The gist is that its something to do with the editor you are editting your GEL script with (yes its a bit bizarre huh! :wacko: )

    pcooper - who is a wise fellow wrote:

    That error message is usually an indication that a program script file was edited and save with a different encoding format.
    so just try editting your GEL script in a different text editor before pasting it into Clarity / loading thru XOG etc.


  • 3.  RE: Gel Script to modify XOG output

    Posted Oct 27, 2012 08:16 AM
    Can I please suggest that instead of doing a conversion to string and back to XML, that you either just make direct modifications to the XML in a direct and targeted way:

    <gel:set select="$var//yourElement/@yourAttribute" value="${some_other_var_or_value}" />

    Or if you need more of a sweeping effort through the entire XML to do a 'global' search and replace through it without knowing exactly which elements/attributes to change, that you construct an appropriate XSLT to do it using tags from the XML library (namespace: jelly:org.apache.commons.jelly.tags.xml.XMLTagLibrary).


  • 4.  Re: Gel Script to modify XOG output

    Posted Apr 28, 2016 07:15 PM

    Hi Nick,

    Can you give a little more insight on the syntax here?

     

    I am trying to update

    openForTimeEntry="true"

     

    to

    openForTimeEntry="false"

     

    Would the syntax then be: <core:set select="xogBody//openForTimeEntry/false"?



  • 5.  Re: Gel Script to modify XOG output

    Posted May 17, 2016 10:05 AM

    <gel:set select="$xogBody//@openForTimeEntry" value="false" />

     

    This should set the attribute to false everywhere in the scope of the data presented I think.



  • 6.  Re: Gel Script to modify XOG output

    Posted May 17, 2016 01:59 PM

    Hi Nick,

     

     

     

     

    I tried: <gel:set select="$xogBody//@openForTimeEntry" value="false" />

    After my "XOG" Read statement, I have $xogBody in memory.  How do I replace "openForTimeEntry="true"" with "openForTimeEntry="false"" ?

     

    Here is my XOG Read statement:

    <NikuDataBus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../xsd/nikuxog_read.xsd">
      <Header version="6.0.11" action="read" objectType="project" externalSource="NIKU">
        <!-- you change the order by simply swap 1 and 2 number in the name attribute -->
        <args name="order_by_1" value="name"/>
        <args name="order_by_2" value="projectID"/>
        <args name="include_tasks" value="false"/>
        <args name="include_dependencies" value="false"/>
        <args name="include_subprojects" value="false"/>
        <args name="include_resources" value="true"/>
        <args name="include_baselines" value="false"/>
        <args name="include_allocations" value="true"/>
        <args name="include_estimates" value="false"/>
        <args name="include_actuals" value="false"/>
        <args name="include_custom" value="false"/>
        <args name="include_burdening" value="false"/>
      </Header>

      <Query>

          <Filter name="projectID" criteria="EQUALS">${v_email_data.rows[0].ProjectID}</Filter>

      </Query>
    </NikuDataBus>

     

     

    Here is what I tried:

    <gel:set select="$xogBody" asString="true" var="xogTemp" />

    <gel:set select="$xogTemp//@openForTimeEntry" value="false" />

     

     

    This syntax gives me the following error:

    org.apache.commons.jelly.JellyTagException: null:388:72: <gel:set> Missing or invalid XML

    at com.niku.union.gel.tags.SetTag.doTag(SetTag.java:137)

    at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:247)

    at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:95)

    at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:186)

    at org.apache.commons.jelly.tags.core.WhenTag.doTag(WhenTag.java:46)

    at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:247)

    at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:95)

    at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:186)

    at org.apache.commons.jelly.tags.core.ChooseTag.doTag(ChooseTag.java:38)

    at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:247)

    at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:95)

    at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:186)

    at org.apache.commons.jelly.tags.core.OtherwiseTag.doTag(OtherwiseTag.java:41)

    at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:247)

    at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:95)

    at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:186)

    at org.apache.commons.jelly.tags.core.ChooseTag.doTag(ChooseTag.java:38)

    at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:247)

    at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:95)

    at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:186)

    at com.niku.union.gel.tags.ScriptTag.doTag(ScriptTag.java:20)

    at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:247)

    at com.niku.union.gel.GELScript.run(GELScript.java:67)

    at com.niku.union.gel.GELController.invoke(GELController.java:74)

    at com.niku.bpm.services.ExecuteCustomAction.run(ExecuteCustomAction.java:207)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

    at java.lang.Thread.run(Thread.java:745)

    Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to org.w3c.dom.Node

    at org.jaxen.dom.DocumentNavigator.getChildAxisIterator(DocumentNavigator.java:152)

    at org.jaxen.util.DescendantAxisIterator.next(DescendantAxisIterator.java:129)

    at org.jaxen.expr.DefaultStep.evaluate(DefaultStep.java:154)

    at org.jaxen.expr.DefaultLocationPath.evaluate(DefaultLocationPath.java:140)

    at org.jaxen.expr.DefaultPathExpr.evaluate(DefaultPathExpr.java:142)

    at org.jaxen.expr.DefaultXPathExpr.asList(DefaultXPathExpr.java:102)

    at org.jaxen.BaseXPath.selectNodesForContext(BaseXPath.java:674)

    at org.jaxen.BaseXPath.selectNodes(BaseXPath.java:213)

    at org.jaxen.BaseXPath.selectSingleNode(BaseXPath.java:234)

    at com.niku.union.gel.tags.SetTag.doTag(SetTag.java:47)

    ... 27 more

    Root cause

    java.lang.ClassCastException: java.lang.String cannot be cast to org.w3c.dom.Node

    at org.jaxen.dom.DocumentNavigator.getChildAxisIterator(DocumentNavigator.java:152)

    at org.jaxen.util.DescendantAxisIterator.next(DescendantAxisIterator.java:129)

    at org.jaxen.expr.DefaultStep.evaluate(DefaultStep.java:154)

    at org.jaxen.expr.DefaultLocationPath.evaluate(DefaultLocationPath.java:140)

    at org.jaxen.expr.DefaultPathExpr.evaluate(DefaultPathExpr.java:142)

    at org.jaxen.expr.DefaultXPathExpr.asList(DefaultXPathExpr.java:102)

    at org.jaxen.BaseXPath.selectNodesForContext(BaseXPath.java:674)

    at org.jaxen.BaseXPath.selectNodes(BaseXPath.java:213)

    at org.jaxen.BaseXPath.selectSingleNode(BaseXPath.java:234)

    at com.niku.union.gel.tags.SetTag.doTag(SetTag.java:47)

    at org.apache.commons.jelly.impl.TagScript.run(TagScript.java:247)

    at org.apache.commons.jelly.impl.ScriptBlock.run(ScriptBlock.java:95)

    at org.apache.commons.jelly.TagSupport.invokeBody(TagSupport.java:186)

    at org.apache.commons.jelly.tags.core.WhenTag.doTag(WhenTag.java:46)

    at org.apache.commons.jelly.impl.TagScript.r...



  • 7.  Re: Gel Script to modify XOG output

    Posted May 17, 2016 02:50 PM

    Much like a previous answer I gave, converting the XML into a string and trying to manipulate it, is not a good way to work.

     

    So this line shouldn't be in your script: <gel:set select="$xogBody" asString="true" var="xogTemp" />

     

    With the exception of maybe wanting to log the value so you can see it.

     

    The log is telling you the problem: null:388:72: <gel:set> Missing or invalid XML

     

    It's not XML because it was converted to a string.  At that point you cannot use XML library functions to manipulate it.

     

    Then since you don't have xogTemp anymore (or it is not applicable) you would then change your second <gel:set> to xogBody instead - as per the example I gave.

     

    That said - I ran a quick test and whilst mine didn't fail to run, it didn't produce the results I had assumed it would give.

     

    Here's the test example:

    <gel:script
      xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary"
    >

     

      <gel:parse var="testdata">
        <dummydata>
          <project id="12345" start="2016-05-17T00:00:00" name="test" openForTimeEntry="true">
            <tasks>
              <task id="abc" openForTimeEntry="true" />
              <task id="def" openForTimeEntry="true" />
              <task id="ghi" openForTimeEntry="false" />
            </tasks>
          </project>
        </dummydata>
      </gel:parse>

     

      <gel:set select="$testdata//@openForTimeEntry" value="false" />

      <gel:set select="$testdata" asString="true" var="testtext" />

      <gel:out>${testtext}</gel:out>
    </gel:script>

    It's output:

    C:\Clarity\misc\gels>gel attribute_update.gel

     

    <?xml version="1.0" encoding="UTF-8"?>

    <dummydata>
      <project id="12345" name="test" openForTimeEntry="false" start="2016-05-17T00:00:00">
        <tasks>
          <task id="abc" openForTimeEntry="true"/>
          <task id="def" openForTimeEntry="true"/>
          <task id="ghi" openForTimeEntry="false"/>
        </tasks>
      </project>
    </dummydata>

     

    C:\Clarity\misc\gels>

     

    You'll see it didn't affect everything, just the first occurrence at project level and not the task ones.

     

    Whilst a <gel:set select= .../> does bring back a nodeset (potential for returning more than one value at once), the value="..." attribute only applies to the first node it finds that meets the criteria, not all of them.  I may raise this as a potential defect based on the (to me) unexpected behaviour, but it may be working as expected and be just something that we ought to document.

     

    It does mean that whilst this approach I mentioned can be used sometimes, there are other times it's not suitable.  For that, I would recommend using XSLT instead.  It is a bit more to add to the GEL script to make it work, but will have the capability of making global sweeping changes through an XML document.

     

    I have previously written how this method works if you would like to try it - I would suggest trying it as I have it before attempting to work/integrate it into your current scripts, if you are not too familiar yet with things like XSLT: Modifying XML/HTML using XSLT in a GEL script



  • 8.  Re: Gel Script to modify XOG output

    Posted May 17, 2016 03:42 PM

    Example with XSLT, modifying my above script and merging it into the blog post I linked to, to make it more relevant to your requirements:

     

    <gel:script
      xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary"
      xmlns:x="jelly:org.apache.commons.jelly.tags.xml.XMLTagLibrary"
    >

     

      <gel:parse var="testdata">
        <dummydata>
          <project id="12345" start="2016-05-17T00:00:00" name="test" openForTimeEntry="true">
            <tasks>
              <task id="abc" openForTimeEntry="true" />
              <task id="def" openForTimeEntry="false" />
              <task id="ghi" openForTimeEntry="true" />
            </tasks>
          </project>
        </dummydata>
      </gel:parse>

     

    <!-- creating a variable to hold my transformation stylesheet -->
    <!-- note that it contains 2 XSL templates; the first is a 'copy everything' template
         the second is one that intercepts - in our case - IMG tags and replaces the attribute
         from one that works (but is invalid, just a placeholder) called rsc to src with
         the same value -->
    <gel:parse var="src_xsl">
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>

      <xsl:template match="@openForTimeEntry" >
        <xsl:attribute name="openForTimeEntry">false</xsl:attribute>
      </xsl:template>
    </xsl:stylesheet>
    </gel:parse>

     

    <!-- we have the variables recreated using the XML tag library's own parser -->
    <x:parse var="xog_xsl"><gel:include select="$src_xsl" /></x:parse>
    <x:parse var="testdata"><gel:include select="$testdata" /></x:parse>

     

    <!-- now we invoke the XML taglib's transformation tag to perform the work of applying the
         stylesheet changes to the input, the result being emitted into the surrounding GEL
         parse call to have the data back into a format desired by the other GEL variable
         processing tags for further use in the script -->
    <gel:parse var="src_corrected">
      <x:transform xml="${testdata}" xslt="${xog_xsl}" />
    </gel:parse>

     

    <!-- just outputting the results into a process instance message so we can see what this
         demo has done -->
    <gel:set select="$src_corrected" var="xog_output" asString="true" />


    <gel:out>${xog_output}</gel:out>

     

    <!-- do stuff -->

     

    </gel:script>

     

    The output:

     

    C:\Clarity\misc\gels>gel attribute_update2.gel

     

    <?xml version="1.0" encoding="UTF-8"?>
    <dummydata>
      <project id="12345" name="test" openForTimeEntry="false" start="2016-05-17T00:00:00">
        <tasks>
          <task id="abc" openForTimeEntry="false"/>
          <task id="def" openForTimeEntry="false"/>
          <task id="ghi" openForTimeEntry="false"/>
        </tasks>
      </project>
    </dummydata>

     

    C:\Clarity\misc\gels>

     

    Hope that helps.



  • 9.  Re: Gel Script to modify XOG output

    Posted May 17, 2016 05:47 PM

    Thanks!  I'll try that.  This post looks like what we're trying to modify:

     

    <NikuDataBus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../xsd/nikuxog_project.xsd">

    <Header action="write" externalSource="NIKU" objectType="project" version="14.3.0.298"/>

    <Projects>

    <Project ... (header values)

    projectID="PRJ000530"

    ... (header values)>

    <Resources>

    <Resource availFrom="2014-12-16T08:00:00" availTo="2018-01-09T09:57:00" bookingStatus="15" capitalPercentage="0" defaultAllocation="0"

          isProjectManager="false" lastUpdatedBy="adminuser" lastUpdatedDate="2016-01-14T11:22:21" openForTimeEntry="<b>true</b>" projectRoleID="_BSAC" resourceID="testuser1">

    <AllocCurve/>

    <HardAllocCurve/>

    <SkillAssocs/>

    </Resource>

    <Resource availFrom="2014-12-16T08:00:00" availTo="2018-01-09T09:57:00" bookingStatus="15" capitalPercentage="0" defaultAllocation="0"

          isProjectManager="false" lastUpdatedBy="adminuser" lastUpdatedDate="2016-01-14T11:22:21" openForTimeEntry="<b>true</b>" projectRoleID="_BSAC" resourceID="testuser2">

    <AllocCurve/>

    <HardAllocCurve/>

    <SkillAssocs/>

    </Resource>

    <SkillAssocs/>

    </Resource>

    </Resources>

    <Allocations/>

    <scenarioDependencies/>

    <InvestmentAssociations>

    <Allocations/>

    <Hierarchies/>

    </InvestmentAssociations>

    <General addedBy="projuser1" addedDate="2014-12-09"/>

    <OBSAssocs complete="false">

    <OBSAssoc id="TRGProj" name="Project OBS" unitPath="/All Investments/Day to Day/Day to Day (Workplans)"/>

    </OBSAssocs>

    </Project>

    </Projects>

     

    <b>Trying to modify to this:</b>

     

    <Resource availFrom="2014-12-16T08:00:00" availTo="2018-01-09T09:57:00" bookingStatus="15" capitalPercentage="0" defaultAllocation="0"

          isProjectManager="false" lastUpdatedBy="adminuser" lastUpdatedDate="2016-01-14T11:22:21" openForTimeEntry="<b>false</b>" projectRoleID="_BSAC" resourceID="testuser1">

    <AllocCurve/>

    <HardAllocCurve/>

    <SkillAssocs/>

    </Resource>

    <Resource availFrom="2014-12-16T08:00:00" availTo="2018-01-09T09:57:00" bookingStatus="15" capitalPercentage="0" defaultAllocation="0"

          isProjectManager="false" lastUpdatedBy="adminuser" lastUpdatedDate="2016-01-14T11:22:21" openForTimeEntry="<b>false</b>" projectRoleID="_BSAC" resourceID="testuser2">

    <AllocCurve/>

    <HardAllocCurve/>

    <SkillAssocs/>

    </Resource>

    <SkillAssocs/>

    </Resource>



  • 10.  Re: Gel Script to modify XOG output

    Posted May 20, 2016 06:47 PM

    Hi Nick,

    Sorry to be dense, but, I'm still having some difficulty with the parse statement.

    I issue the XOG command to read out the values.  I reference the Result of that XOG command.  I can write that result to a file.  I can't seem to use that XOG result to modify using the above script.

     

     

    Would the syntax to use the XOG result in an XLST modify script look like this?

    <gel:parse var="emailMsg">

      "$result/SOAP-ENV:Envelope/SOAP-ENV:Body"

    </gel:parse>

     

    The problem is I only get the very top of the XOG result in the output.



  • 11.  Re: Gel Script to modify XOG output

    Posted May 21, 2016 02:27 PM

    I think $results is a string at this point. So to do a xpath you need to get it into a xml docment or pull out the string you need.

     

    Try

    <gel:set asString="true" var="emailMsgString" select="$result/SOAP-ENV:Envelope/SOAP-ENV:Body" />
    <gel:parse var="emailMsg">
        <gel:expr select="$emailMsgString"/>
    </gel:parse>
    

     

    V/r,

    Gene



  • 12.  Re: Gel Script to modify XOG output

    Posted May 23, 2016 07:54 PM

    Hi Gene,

    Nick Darlington said it was not good to convert XML into a string when trying to modify the source.

    I have the code referencing the XOG result, but then, I can't seem to find the syntax to modify the XML result.

    Thanks,

    Lowell



  • 13.  Re: Gel Script to modify XOG output

    Posted May 23, 2016 08:30 PM

    So the <gel:parse> tag accepts three input types.

    An xml file.

    An InputStreamReader

    or a String.

    So the <gel:set> with the select and asString  attributes just pulls off the node I want to be the parent along with its children, no string modification is occurring.  This is fed into <gel:parse> creates a new XML Document

     

    On a side note:

     

    The gel parse tag creates a org.w3c.dom.Document where as the jelly parse tag creates a org.dom4j.Document object. I have had troubles in the past mixing gel and jelly xml document so I normally do all my transformation on the jelly xml document and a push into a gel xml document when I am ready to use in.

     

    V/r,

    Gene



  • 14.  Re: Gel Script to modify XOG output

    Posted May 26, 2016 01:49 AM

    Hi Gene,

    I'm having some problem with the "<gel:parse>" command.

     

    I have tried to pull the XOG result and this doesn't work: (It gives an error)

    <gel:parse var="emailMsg" select="$result/soapenv:Envelope/soapenv:Body/NikuDataBus" />

     

    I have tried to pull the XOG result and this doesn't work: (It gives an error)

    <gel:parse var="emailMsg">$result</gel:parse>

     

    I have tried this one and it gives an error "tag 'parse' does not have attribute 'xml'":

    <gel:parse var="emailMsg" xml="${PLocalDirectory}/write_${vnow}.xml" />

     

    I give up, how do I read an XML and leave it XML and process it to replace attributes "openForTime="true""?



  • 15.  Re: Gel Script to modify XOG output

    Posted May 26, 2016 10:50 AM

    So I played around with this -- gel:parse really doesn't like to read a string from the context.

     

    Here is how I forced it to read a string.

     

    <gel:script xmlns:core="jelly:core"
        xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary"
        xmlns:x="jelly:org.apache.commons.jelly.tags.xml.XMLTagLibrary"
        xmlns:aw="http://www.adventure-works.com"
        >
    
        <!-- a org.w3c.dom.Document which is what gel uses -->
        <gel:parse var="testdata">
            <dummydata>
                <project id="12345" start="2016-05-17T00:00:00" name="test" openForTimeEntry="true">
                    <tasks>
                        <task id="abc" openForTimeEntry="true" />
                        <task id="def" openForTimeEntry="true" />
                        <task id="ghi" openForTimeEntry="false" />
                    </tasks>
                </project>
            </dummydata>
        </gel:parse>
        
        <!-- convert it to a string for use in a dom4j document -->
        <gel:set asString="true" var="xmlString" select="$testdata/dummydata" />  
        <gel:out>${xmlString}</gel:out>
    
        <!-- create our dom4j document and interate over our nodes containing openForTimeEntry -->
        <x:parse var="dom4JDocument" text="${xmlString}" />
        <x:forEach var="dom4jNode" select="$dom4JDocument//*[@openForTimeEntry]">
            <core:expr value='${dom4jNode.setAttributeValue("openForTimeEntry","false")}' />
        </x:forEach>
        
        <!-- convert our dom4j root node into a string and load it into a inputstream -->
        <core:set var="rootXml" value="${dom4JDocument.getRootElement().asXML()}" />
        <core:new var="byteStream" className="java.io.ByteArrayInputStream" >
            <core:arg value="${rootXml.getBytes()}" />
        </core:new>
    
        <!-- gel:parse is finicky about how it reads a string so force it to eat a inputstream -->
        <gel:parse var="updateXML" file="${byteStream}" />
        
        <!-- show our results from the org.w3c.dom.Document -->
        <gel:set asString="true" var="testtext" select="$updateXML/dummydata" />  
        <gel:out>${testtext}</gel:out>
    
    </gel:script>
    

     

     

    V/r,

    Gene



  • 16.  Re: Gel Script to modify XOG output

    Posted Jun 01, 2016 06:53 PM

    Hi nick_darlington ,

    Your syntax worked!  I was getting the errors on the first times I ran the code.  After a restart of services, it worked fine.  Probably a caching issue on my side.

    Thanks for your help on this,

    Lowell



  • 17.  RE: Gel Script to modify XOG output

    Posted Nov 18, 2012 07:02 AM
    Plidian,

    Just wondering if you were able to make the gel script work and if you would be willing to share. I have a similar requirement in my env.

    Thanks
    Atul


  • 18.  Re: Gel Script to modify XOG output

    Broadcom Employee
    Posted May 16, 2016 12:01 PM

    You can change any attribute value from gel script.



  • 19.  Re: Gel Script to modify XOG output

    Broadcom Employee
    Posted May 21, 2016 11:23 PM

    No need XSLT to change the attribute value.

     

    look at below example.

     

    Example:

     

    <gel:set select="$v_xml_root/soapenv:Envelope/soapenv:Body/NikuDataBus/Users/User/@userStatus/text()" value="ACTIVE"/>



  • 20.  Re: Gel Script to modify XOG output

    Posted May 23, 2016 10:17 AM

    As above, this only works for a single (or for the first) attribute value, it doesn't apply it to all @userStatus attribute instances in the entire document.



  • 21.  Re: Gel Script to modify XOG output

    Posted Jul 01, 2016 08:49 AM

    Could this approach be used to remove a section from the XML file?

    For example, a project read xog includes an <InvestmentAssociations> section (even if include_subprojects=false is included in the read xog). So if the detail of this project read is used to generate a new project, the subprojects/investment associations are created too, which I don't want. So in my GEL script, can I remove the <InvestmentAssociations> section using the XSLT approach described above (or by any other means?).

    Thank you.



  • 22.  Re: Gel Script to modify XOG output

    Posted Jul 01, 2016 10:21 AM

    XSLT can perform those kind of manipulations, yes.

     

    You'd need a minimum (and possibly maximum) of 2 templates in the XSLT file.

     

    One of them is the 'copy/process everything' template:

     

      <xsl:template match="@*|node()">

        <xsl:copy>

          <xsl:apply-templates select="@*|node()"/>

        </xsl:copy>

      </xsl:template>

     

    And the apply-templates instruction in here allows for further analysis to be done during the copy, for which you'd want the 'match my item and then do nothing' template, which suppresses the element from being output/copied:

     

      <xsl:template match="InvestmentAssociations" />

     

    That is for matching elements, if you want to match (remove) attributes but keep the elements, then create an empty template like above but prefix the attribute name with @ instead.  Elements need no 'decoration' in front of their names.



  • 23.  Re: Gel Script to modify XOG output

    Posted Jul 01, 2016 10:53 AM

    Many thanks Nick.

    Glad to know it can be done.

    Your explanation is a tad cryptic but perhaps once I've tried it, all will become clear!

    Thanks again

    Vince



  • 24.  Re: Gel Script to modify XOG output

    Posted Jul 03, 2016 11:26 AM

    Wow! It worked!

    Amazing. Thank you.



  • 25.  Re: Gel Script to modify XOG output

    Posted Aug 10, 2016 05:04 PM

    Hello again Nick.

    I have another variation and I wonder if you can help me again.

    I need to change certain attribute values, but not all instances of them.

    In the Project Dependencies section, the dependencies are listed with the related project, which may or may or may not be the 'current' project. When xogging project A to project B, I need to change the internal dependencies (so Project A becomes Project B) but not the external dependencies to another project. So given the following xml, I need to change project A to project B but leave project X alone.

    <Dependencies>

    <Dependency lag="0" lag-type="days" predProjectID="projectA" predTaskID="abc" succProjectID="projectA" succTaskID="xyz" type="finish-start"/>

    <Dependency lag="0" lag-type="days" predProjectID="projectA" predTaskID="abc" succProjectID="projectX" succTaskID="Completion" type="finish-start"/>

    </Dependencies>

     

    The code below changes all successor and predecessor projects, which would be fine if they were all internal dependencies. Is it possible to be selective about which 'matches' are changed?

     

    <gel:parse var="pname_xsl">

      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

       <xsl:template match="@*|node()">

        <xsl:copy>

         <xsl:apply-templates select="@*|node()"/>

        </xsl:copy>

       </xsl:template>

       <xsl:template match="@predProjectID=" />

       <xsl:attribute name="predProjectID">${newcode}</xsl:attribute>

       <xsl:template match="@succProjectID" />

       <xsl:attribute name="succProjectID">${newcode}</xsl:attribute>

      </xsl:stylesheet>

    </gel:parse>

     

    Many thanks

     

    Vince



  • 26.  Re: Gel Script to modify XOG output

    Posted Aug 11, 2016 03:05 PM

    The way the templates work is that when a match is made, the information inside the template is going to be applied.

     

    So an 'empty template', that is, one that just closes the template tag with nothing inside it like:

     

    <xsl:template match="@succProjectID" />

     

    or:

     

    <xsl:template match="@succProjectID">

    </xsl:template>

     

    Are basically saying whenever these items are matched, don't output anything.  Also known as a 'do nothing' template, but rather than doing nothing they are actually erasing those items from the output.

     

    So what you want to craft is a match expression for your problem, and then inside that template an action to do instead of either erasing or merely copying the current values to the output.  In other words, any operations like <xsl:attribute ... /> should be contained inside the tags of the <xsl:template ...> ... </xsl:template> you want to apply them to, not outside of them.

     

    The other trick involved here is that the match can impact where you are in the XML document right now, as well as everything nested inside that part of the document.

     

    One way to just start with identifying the records you want to impact will be with a match expression similar to the following:

     

    <xsl:template match="Dependency[@succProjectID=@predProjectID]">

      <!-- do something -->

    </xsl:template>

     

    This is saying that it should stop and do some kind of special processing for every Dependency element where the two ends of the dependency have the same project (inter-project dependency type).

     

    But this then runs the <!-- do something --> instructions on the Dependency tag and all its nested children (all the attributes and any other nodes/elements below it), so you are probably wanting to do something a bit more selective where by you identify this set of records to work on, but then you are only impacting the specific attributes and leaving the rest alone.

     

    There are ways to do that, too, but I'll have to see if I can come back to put more light on that topic as it would take a while to figure it out.

     

    I hope that helps explain XSL templates behaviour a bit more for now though.



  • 27.  Re: Gel Script to modify XOG output

    Posted Aug 15, 2016 06:37 AM

    Many thanks Nick for your usual detailed explanation.

    I'll do some tests around your suggestions.

    As you suspected, while there are some dependencies where both ends are the same, there are others (and this is nub of the problem) where one end refers to a different project.

    Thanks for your time and input. Greatly appreciated.

    Kind regards

    Vince