1
votes

I need help in removing parent nodes from below given XML using XSLT..

<?xml version="1.0" encoding="UTF-8"?>
<Report xmlns="OpenProblems2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="OpenProblems2" Name="OpenProblems2">
   <Hello>
      <NewDataSet>
         <Table>
            <a>1832874</a>
            <b>HUME-9063</b>
            <c>not informed</c>
         </Table>
         <Table>
            <a>1832874</a>
            <b>HUME-9063</b>
            <c>not informed</c>
         </Table>
      </NewDataSet>
   </Hello>
</Report>

Output should look like -

<NewDataSet>
<Table>
  <a>1832874</a> 
  <b>HUME-9063</b> 
  <c>not informed</c>
</Table>
<Table>
  <a>1832874</a> 
  <b>HUME-9063</b> 
  <c>not informed</c>
</Table>
</NewDataSet>

XSLT should remove Report,Hello & NewDataset elements. please... your help will be highly appreciated.

3
You can enter the XML code directly in the editor and then use the "{}" button to mark it as a code sapleNic Gibson

3 Answers

1
votes

The standard approach to make small changes to an XML file using XSLT is to define an identity template, which copies everything from input to output as-is except where overridden by a more specific template:

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

and then provide specific templates to match the things you want to change. In this case if you know there will always be exactly one third-level element (the NewDataSet) then you could skip the first two levels of outer wrapping elements using

<xsl:template match="/">
  <xsl:apply-templates select="*/*/*" />
</xsl:template>

these two templates together would produce output like this

<NewDataSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="OpenProblems2">
<Table>
  <a>1832874</a> 
  <b>HUME-9063</b> 
  <c>not informed</c>
</Table>
<Table>
  <a>1832874</a> 
  <b>HUME-9063</b> 
  <c>not informed</c>
</Table>
</NewDataSet>

If you also want to remove all the namespaces then you need to add a third template like this:

<xsl:template match="*">
  <xsl:element name="{local-name()}">
    <xsl:apply-templates select="@*|node()" />
  </xsl:element>
</xsl:template>

to take any element in any (or no) namespace and replace it with a new element with the same local name but not in a namespace.

1
votes

If you want to leave the namespace as it is, then all you need is

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

    <xsl:template match="/">
        <xsl:copy-of select="o:NewDataSet"/>
    </xsl:template>

</xsl:stylesheet>
0
votes

This sort of requirement is best dealt with using an identity template. The identity template will allow you to pass through the majority of your XML unchanged and then process only the pieces that are necessary. A simple identity looks like:

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

This matches all attributes, comments, elements, etc and copies them to the output. Any more specific match will take precedence.

Your sample output doesn't actually remove the NewDataSet element so I haven't either. If you want to remove it, add it to the template below (but remember that it will make your output ill-formed)

<xsl:template match="Hello|Report">
    <xsl:apply-templates/>
</xsl:template>

This template matches both Hello and Report elements and processes them by simply applying templates to their children without copying the actual node to the output.

So, a stylesheet such as:

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

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

    <xsl:template match="Hello|Report">
        <xsl:apply-templates/>
    </xsl:template>

</xsl:stylesheet>

will take your sample input and generate your sample output. As @ian-roberts points out, if you really did want to strip out the namespace you would need to handle that too.