Expand my Community achievements bar.

Enhance your AEM Assets & Boost Your Development: [AEM Gems | June 19, 2024] Improving the Developer Experience with New APIs and Events

Invalid XML character error when indexing XML node

Avatar

Former Community Member

All

I have an XML document of the following form:

<RootNode>

     <ChildNode>

          <ChildA/>

          <ChildB/>

          <ChildC/>

     </ChildNode>

     <ChildNode>

          <ChildA/>

          <ChildB/>

          <ChildC/>

     </ChildNode>

</RootNode>

What I need is a means to insert a new node underneath one of the <ChildNode> elements.  However, this requires indexing to specify which <ChildNode> I'd like to add to.  So, using a SetValue, I have the following left-hand side of an expression:

/process_data/xmlVar/RootNode/ChildNode[2]/NewNode

and on the right-hand side of the expression:

'test'

However, the above throws an XML parsing error stating that an "invalid XML character was specified".  If I simply remove the indexing from the left-hand side to yield:

/process_data/xmlVar/RootNode/ChildNode/NewNode

the SetValue properly adds the node <NewNode> but it does so under the first <ChildNode> - which I understand.

So my question is simply:  "How does one index their XML expression properly when trying to dynamically build XML?"  I have tried putting both single quotes and double quotes around the index but to no avail.

Thanks in advance.

4 Replies

Avatar

Former Community Member

XPath is not your friend when it comes to adding nodes. XSLT is not necessarily your friend either but it works.

I built the attached process to insert a third 'ChildNode'

     <ChildNode>

          <ChildA>A3</ChildA><ChildB>B3</ChildB><ChildC>C3</ChildC>

     </ChildNode>

into

<RootNode>
     <ChildNode>
          <ChildA>A1</ChildA><ChildB>B1</ChildB><ChildC>C1</ChildC>
     </ChildNode>
     <ChildNode>

          <ChildA>A2</ChildA><ChildB>B2</ChildB><ChildC>C2</ChildC>
     </ChildNode>
</RootNode>

to produce

<RootNode>
      <ChildNode>
           <ChildA>A1</ChildA><ChildB>B1</ChildB><ChildC>C1</ChildC>
      </ChildNode>
      <ChildNode>

          <ChildA>A2</ChildA><ChildB>B2</ChildB><ChildC>C2</ChildC>
      </ChildNode>

     <ChildNode>

          <ChildA>A3</ChildA><ChildB>B3</ChildB><ChildC>C3</ChildC>

     </ChildNode>

</RootNode

The XSLT goes like this

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:param name="childA">ChildA</xsl:param>
  <xsl:param name="childA_text">{$ /process_data/@childNodeA $}</xsl:param>
  <xsl:param name="childB">ChildB</xsl:param>
  <xsl:param name="childB_text">{$ /process_data/@childNodeB $}</xsl:param>
  <xsl:param name="childC">ChildC</xsl:param>
  <xsl:param name="childC_text">{$ /process_data/@childNodeC $}</xsl:param>
  <xsl:output method="xml" encoding="utf-8"/>
  <xsl:template match="@*|node()">
     <xsl:copy>
       <xsl:apply-templates select="@*|node()"/>
     </xsl:copy>
  </xsl:template>
  <xsl:template match="RootNode">
     <xsl:copy>
         <xsl:apply-templates/>
          <xsl:if test="position()=last()">
             <ChildNode>
        <xsl:element name="{$childA}"><xsl:value-of select="$childA_text"/></xsl:element>
        <xsl:element name="{$childB}"><xsl:value-of select="$childB_text"/></xsl:element>
        <xsl:element name="{$childC}"><xsl:value-of select="$childC_text"/></xsl:element>
         </ChildNode>
          </xsl:if>
     </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Steve

Avatar

Level 2

Hi Steve,

Never heard back from you. If you can't help, please let me know.

Besy,

Rob

Avatar

Level 2

Sorry,

Best,

Rob

Sent via BlackBerry from T-Mobile