YoannD

Gel: Insert an attribute to an XML element when it doesn't exist

Blog Post created by YoannD Employee on Apr 3, 2018

Some time ago I would like to populate some new attribute inside an XML element, and obviously I've discovered that is not possible with our gelScript language. For example if you try this :

<gel:script xmlns:core="jelly:core" xmlns:gel="jelly:com.niku.union.gel.GELTagLibrary">
     <gel:parse var="xmlData">
          <A>
               <B name="ID001" toto="TITI"/>
               <B name="ID002"/>
          </A>
     </gel:parse>
     <gel:out>[i] Initial value of the XML Document</gel:out>
     <gel:expr select="$xmlData"/>
     <gel:out/>
     <!-- Here we try to change an existing attribute -->
     <gel:out>[i] Changing the value of attribute named 'toto' to 'HELO!'</gel:out>
     <gel:set select="$xmlData/A/B[1]/@toto" value="HELO!"/>
     <gel:expr select="$xmlData"/>
     <gel:out/>
</gel:script>

It will work as expected :

[i] Initial value of the XML Document
<![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<A>
  <B name="ID001" toto="TITI"/>
  <B name="ID002"/>
</A>
]]>
[i] Changing the value of attribute named 'toto' to 'HELO!'
<![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<A>
  <B name="ID001" toto="HELO!"/>
  <B name="ID002"/>
</A>
]]>

Now we will try to add a new attribute "toto" to the next B's element, we would logically add the following sentences :

<!-- Here we try to add a new attribute called "toto" -->    
<gel:out>[i] Adding a new attribute named 'toto' set to 'BYE!'</gel:out>   
<gel:set select="$xmlData/A/B[2]/@toto" value="BYE!" insert="true"/>   
<gel:expr select="$xmlData"/>  
<gel:out/>

And when you try to run this you get this error :

[i] Adding a new attribute named 'toto' set to 'BYE!'
Internal error: file:/D:/_NIKU_/_GDOC_/03_STUDIO/04_GEL/GelSet/Exemple02.xml:29:70: <gel:set> Missing or invalid XML

This error is due to the fact that the attribute entry doesn't exist for our second B element. So we need to add it, and the insert="true" is not sufficient to do it.

I've try the the following without success :

<gel:parse var="newAttElt"><B toto="Bye!"/></gel:parse>

<gel:set select="$xmlData/A/B[2]" value="${newAttElt/@toto}" insert="true"/>

or

<gel:parse var="newAttElt"><B toto="Bye!"/></gel:parse>
<gel:set var="newAtt" select="$newAttElt/B/@toto"/>
<gel:set select="$xmlData/A/B[1]" value="${newAtt}" insert="true"/>

Finally with some litle reverse engineering I've found the following :

<!-- Here we try to add a new attribute called "toto" -->
    <gel:out>[i] Adding a new attribute named 'toto' set to 'BYE!'</gel:out>
    
    <gel:set var="MyNode" select="$xmlData/A/B[2]"/>
    <core:set value="${MyNode.setAttribute('toto','Bye!')}" var="dummy"/>
    
    <gel:expr select="$xmlData"/>
    <gel:out/>

We get the expected result:

[i] Initial value of the XML Document
<![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<A>
  <B name="ID001" toto="TITI"/>
  <B name="ID002"/>
</A>
]]>
[i] Changing the value of attribute named 'toto' to 'HELO!'
<![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<A>
  <B name="ID001" toto="HELO!"/>
  <B name="ID002"/>
</A>
]]>
[i] Adding a new attribute named 'toto' set to 'BYE!'
<![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<A>
  <B name="ID001" toto="HELO!"/>
  <B name="ID002" toto="Bye!"/>
</A>
]]>

We need to pass by a temporary object to call the setAttribute method, it works perfectly with Clarity from 13.X at least.

You may also explore the following methods : getAttributes().getLength() ; getAttibutes().item(n).getName() ; and many other...

 

Enjoy

Outcomes