0

I have below list with arrays having same name(json:array name="member"). I am trying to rename them something meaningful (json:array name="member1") so they remain unique values. I am trying to use identity template.

Input:

<json:object xmlns:json="http://www.ibm.com/xmlns/prod/2009/jsonx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <json:array xmlns:dpfunc="http://www.datapower.com/extensions/functions" xmlns:str="http://exslt.org/strings" name="benefits">
      <json:object>
         <json:string name="ArrayCode">A</json:string>
         <json:array name="member">
            <json:object>
               <json:string name="memberID">A-001</json:string>
            </json:object>
         </json:array>
         <json:array name="member">
            <json:object>
               <json:string name="memberID">A-002</json:string>
            </json:object>
         </json:array>
         <json:array name="member">
            <json:object>
               <json:string name="memberID">A-003</json:string>
            </json:object>
         </json:array>
      </json:object>
      <json:object>
         <json:string name="ArrayCode">B</json:string>
         <json:array name="member">
            <json:object>
               <json:string name="memberID">B-001</json:string>
            </json:object>
         </json:array>
         <json:array name="member">
            <json:object>
               <json:string name="memberID">B-002</json:string>
            </json:object>
         </json:array>
         <json:array name="member">
            <json:object>
               <json:string name="memberID">B-003</json:string>
            </json:object>
         </json:array>
      </json:object>
   </json:array>
</json:object>

Expected Output:

   <json:object xmlns:json="http://www.ibm.com/xmlns/prod/2009/jsonx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <json:array xmlns:dpfunc="http://www.datapower.com/extensions/functions" xmlns:str="http://exslt.org/strings" name="benefits">
      <json:object>
         <json:string name="ArrayCode">A</json:string>
         <json:array name="member1">
            <json:object>
               <json:string name="memberID">A-001</json:string>
            </json:object>
         </json:array>
         <json:array name="member2">
            <json:object>
               <json:string name="memberID">A-002</json:string>
            </json:object>
         </json:array>
         <json:array name="member3">
            <json:object>
               <json:string name="memberID">A-003</json:string>
            </json:object>
         </json:array>
      </json:object>
      <json:object>
         <json:string name="ArrayCode">B</json:string>
         <json:array name="member1">
            <json:object>
               <json:string name="memberID">B-001</json:string>
            </json:object>
         </json:array>
         <json:array name="member2">
            <json:object>
               <json:string name="memberID">B-002</json:string>
            </json:object>
         </json:array>
         <json:array name="member3">
            <json:object>
               <json:string name="memberID">B-003</json:string>
            </json:object>
         </json:array>
      </json:object>
   </json:array>
</json:object>

XSLT I tried with Identity template and for-each to loop through array list.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="http://exslt.org/dates-and-times" xmlns:dp="http://www.datapower.com/extensions" xmlns:dpfunc="http://www.datapower.com/extensions/functions" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:json="http://www.ibm.com/xmlns/prod/2009/jsonx" xmlns:str="http://exslt.org/strings" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://www.datapower.com/schemas/json jsonx.xsd" extension-element-prefixes="dp" exclude-result-prefixes="xsl fo xs fn dp date">
   
   <xsl:template match="@* | node()">
      <xsl:copy>
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
   </xsl:template>
   
   
   <xsl:template match="json:array/@name">
      <xsl:for-each select="json:object/json:array">
         <xsl:attribute name="@name{position()}">
            <xsl:value-of select="@name"/>
         </xsl:attribute>
      </xsl:for-each>  
   </xsl:template>
   
</xsl:stylesheet>

No change is happening to input with above code. I guess using for-each is wrong here. But how can I reach array names nested inside.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
Mano
  • 143
  • 1
  • 2
  • 13
  • Using array name so it applies only to inside array and xsl:number instead of position - I can see the output as expected. Thank you. – Mano Dec 04 '21 at 19:45

2 Answers2

1

Perhaps

<xsl:template match="json:array[@name = 'member']">
    <xsl:copy>
        <xsl:attribute name="name">
            <xsl:value-of select="@name"/>
            <xsl:number/>
        </xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

helps if you know the name of the array.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
0

If you want to use the position of the json:array within its parent json:object, then your template should match json:array - say:

<xsl:template match="json:array">
    <xsl:copy>
        <xsl:attribute name="name">
            <xsl:value-of select="@name" />
            <xsl:value-of select="position()" />
        </xsl:attribute>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

However you need to keep in mind that:

  1. this will number ALL json:array elements, including the top level one; and
  2. the position of the first json:array within your json:object is 2, not 1. The first position is occupied by the json:string element.
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Above approach is giving member4, member6, member8 etc when applied on input XML. Instead of applying on name attribute which is already coming above, is there any way I can apply exclusively on json:array present inside so it can be member1, member2, ,member3. – Mano Dec 04 '21 at 19:31
  • No, it is giving member2, member3, member4 etc. - see: https://xsltfiddle.liberty-development.net/6qjt5R8. As for processing only some array elements, you need to provide the rules that can be used for this. All we have is one example. I did not assume that it's OK to hard-code the name of the array (as the accepted answer did). If I wanted to assume that the input will always look like the example, i would have used `position() - 1` to get the numbering you expect. – michael.hor257k Dec 04 '21 at 20:30
  • I think using xsl:number here is more reliable, it makes the answer less sensitive to whitespace in the input, as well as other extraneous element nodes. – Michael Kay Dec 05 '21 at 09:47