Transforming multiple XML element occurrence into one element occurrence using XSLT

Here should go questions about transforming XML with XSLT and FOP.
allydott
Posts: 1
Joined: Tue Apr 12, 2022 9:43 pm

Transforming multiple XML element occurrence into one element occurrence using XSLT

Post by allydott »

Hi,
I've been trying for many weeks to learn XML transformation using XSLT by learning on the Internet to transform my input xml to a transformed output xml, but right now I am stuck in this transformation requirement and I am not able to proceed further from here so if my question format is not good, I apologize for it. I have added my sample input xml, sample output xml and the XSLT code I tried this transformation with.

Sample input xml :

Code: Select all

<root>
  <C>........</C>           
  <AElement name="........" item="........" />
  ...
  <AElement name="........">
    <T>
       ..
       ..
    </T>    
  </AElement>              
  <AElement name="PaperVal">      <!-- this starts here-->
    <DStruct>
      <FillLine name="PaperVal">
        <Z>
          <C>........</C>
          <AElement name="........" item="........" />
          <AElement name="........">
            <T>
              ..
            </T>
          </AElement>
        </Z>
      </FillLine>
    </DStruct>
  </AElement>             <!-- this ends here-->
  <AElement name="PageNum">    <!-- this starts here -->
    <DStruct>
      <FillLine name="PageNum">
        <Z>
          <C>........</C>
          <AElement name="........" item="........" />
           ..
        </Z>
      </FillLine>
    </DStruct>
  </AElement>          <!-- this ends here-->
  ...
  ...
  <AElement name="...">       <!-- this starts here -->
    <DStruct>
      <FillLine name="...">
        ...
      </FillLine>
    </DStruct>
  </AElement>               <!-- this ends here-->
  <AElement name="........" item="........" />
</root>
The above sample input xml needs to be transformed to this output xml :

Code: Select all

<root>
  <C>........</C>           
  <AElement name="........" item="........" />
  ...
  <AElement name="........">
    <T>
       ..
       ..
    </T>    
  </AElement>              
  <AElement name="MainValue">     <!-- this starts here -->
    <DStruct>
      <FillLine name="PaperVal">
        <Z>
          <C>........</C>
          <AElement name="........" item="........" />
          <AElement name="........">
            <T>
              ..
            </T>
          </AElement>
        </Z>
      </FillLine>
    </DStruct>
    <DStruct>
      <FillLine name="PageNum">
        <Z>
          <C>........</C>
          <AElement name="........" item="........" />
           ..
        </Z>
      </FillLine>
    </DStruct>
  ...
  ...
    <DStruct>
      <FillLine name="...">
        ...
      </FillLine>
    </DStruct>
  </AElement>       <!-- this ends here-->
  <AElement name="........" item="........" />
</root>
Transformation Requirement: I need to transform

Code: Select all

<AElement name="PaperVal">
,

Code: Select all

<AElement name="PageNum">
, and the following future

Code: Select all

<AElement name="...">
elements to be transformed into one single element

Code: Select all

<AElement name="MainValue">
. In the input xml file,

Code: Select all

<AElement name="....">
is opened and closed in every position which I have mentioned using this comment <!-- this starts here--> & <!-- this ends here-->. I need to transform this to one single element defined as

Code: Select all

<AElement name="MainValue">
which starts once at the line mentioned in the output xml as <!-- this starts here --> and ends at <!-- this ends here-->. The rest of the content of the xml needs to be returned as it is as displayed in the above output xml file, transformation is needed only for this element.

The XSLT I'm using right now is this :

Code: Select all

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template> 

<xsl:template match="AElement/@name[. = 'PaperVal']">
   <xsl:attribute name="{name()}">MainValue</xsl:attribute>
</xsl:template>  
</xsl:stylesheet>
But this is changing only the first AElement

Code: Select all

<AElement name="PaperVal">
and not the overall transformation I need. I kept trying with different template matches in this XSLT and tried to achieve the transform I need, but after so much trials I am still stuck here. If someone could please help me out here, I'd be very very thankful. Thank you for reading!
Martin Honnen
Posts: 96
Joined: Tue Aug 19, 2014 12:04 pm

Re: Transforming multiple XML element occurrence into one element occurrence using XSLT

Post by Martin Honnen »

As you are asking in the oXygen forum, I suppose you use oXygen where you have Saxon 10 or 9 to run XSLT 2 or 3 so you can easily use `for-each-group group-adjacent` or `for-each-group starting-with`, have a look at the examples in the XSLT specification on `xsl:for-each-group`.
Even if you are not an oXygen user, XSLT 2 or 3 are available on lots of platforms based on Saxon 9 or 10 or 11 Java, or Saxon 9 or 10 .NET or SaxonC 11 for C/C++ and Python or PHP or with Saxon-JS 2 for Node.js and modern browsers.
Post Reply