1
votes

I need to transform an XML file another XML file but filter out some unneeded records. The output XML file needs to have the exact node structure of the input XML file. I think a simple XSLT file should do this easily.

Here is the sample Input XML file ...

<?xml version="1.0" encoding="utf-8" ?>
<RepeaterData>
  <Version />
  <Items>
    <Item>

      <response type="System.String">xxx</response>
      <response_date type="System.String" />
      <digital_signature_field_profile_name type="System.String">tester3_Dianne</digital_signature_field_profile_name>
      <approver_role type="System.String">tester3</approver_role>
      <approver_workflow_group type="System.Int32">3</approver_workflow_group>
      <approver_workflow_sequence_in_group type="System.Int32">2</approver_workflow_sequence_in_group>

    </Item>
    <Item>

      <response type="System.String">xxx</response>
      <response_date type="System.String" />
      <digital_signature_field_profile_name type="System.String">tester2_Ben</digital_signature_field_profile_name>
      <approver_role type="System.String">tester2</approver_role>
      <approver_workflow_group type="System.Int32">1</approver_workflow_group>
      <approver_workflow_sequence_in_group type="System.Int32">3</approver_workflow_sequence_in_group>
    </Item>
    <Item>

      <response type="System.String" />
      <response_date type="System.String" />
      <digital_signature_field_profile_name type="System.String">tester1_Greg</digital_signature_field_profile_name>
      <approver_role type="System.String">tester1</approver_role>
      <approver_workflow_group type="System.Int32">4</approver_workflow_group>
      <approver_workflow_sequence_in_group type="System.Int32">1</approver_workflow_sequence_in_group>
    </Item>
    <Item>

      <response type="System.String" />
      <response_date type="System.String" />

      <digital_signature_field_profile_name type="System.String">tester4_Erin</digital_signature_field_profile_name>
      <approver_role type="System.String">tester4</approver_role>
      <approver_workflow_group type="System.Int32">3</approver_workflow_group>
      <approver_workflow_sequence_in_group type="System.Int32">2</approver_workflow_sequence_in_group>
    </Item>
    <Item>

      <response type="System.String" />
      <response_date type="System.String" />
      <digital_signature_field_profile_name type="System.String">tester5_Sherry</digital_signature_field_profile_name>
      <approver_role type="System.String">tester5</approver_role>
      <approver_workflow_group type="System.Int32">3</approver_workflow_group>
      <approver_workflow_sequence_in_group type="System.Int32">1</approver_workflow_sequence_in_group>
    </Item>
  </Items>
</RepeaterData>

Here is sample of the desired output XML file (if we filter on response IS NOT empty/null)...

<?xml version="1.0" encoding="utf-8"?>
<RepeaterData>
<Version />
<Items>
<Item>
  <response type="System.String">xxx</response>
  <response_date type="System.String" />
  <digital_signature_field_profile_name type="System.String">tester3_Dianne</digital_signature_field_profile_name>
  <approver_role type="System.String">tester3</approver_role>
  <approver_workflow_group type="System.Int32">3</approver_workflow_group>
  <approver_workflow_sequence_in_group type="System.Int32">2</approver_workflow_sequence_in_group>
</Item>
<Item>
  <response type="System.String">xxx</response>
  <response_date type="System.String" />
  <digital_signature_field_profile_name type="System.String">tester2_Ben</digital_signature_field_profile_name>
  <approver_role type="System.String">tester2</approver_role>
  <approver_workflow_group type="System.Int32">1</approver_workflow_group>
  <approver_workflow_sequence_in_group type="System.Int32">3</approver_workflow_sequence_in_group>
</Item>
</Items>
</RepeaterData>

With some effort I created this XSLT ...

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
    <xsl:for-each select="/">
        <xsl:copy-of select ="RepeaterData/Items/Item[response != '']"/>
    </xsl:for-each>
</xsl:template >
</xsl:stylesheet>

But it produces an XML file with missing nodes. The missig nodes are "RepeaterData", "Version", and "Items".

<?xml version="1.0" encoding="utf-8"?>
<Item>
  <response type="System.String">xxx</response>
  <response_date type="System.String" />
  <digital_signature_field_profile_name type="System.String">tester3_Dianne</digital_signature_field_profile_name>
  <approver_role type="System.String">tester3</approver_role>
  <approver_workflow_group type="System.Int32">3</approver_workflow_group>
  <approver_workflow_sequence_in_group type="System.Int32">2</approver_workflow_sequence_in_group>
</Item>
<Item>
  <response type="System.String">xxx</response>
  <response_date type="System.String" />
  <digital_signature_field_profile_name type="System.String">tester2_Ben</digital_signature_field_profile_name>
  <approver_role type="System.String">tester2</approver_role>
  <approver_workflow_group type="System.Int32">1</approver_workflow_group>
  <approver_workflow_sequence_in_group type="System.Int32">3</approver_workflow_sequence_in_group>
</Item>

One would think there is a generic way to build the XSLT filter without having to manually embed these missing nodes into the XSLT for output.

I looked through samples but could not find something that basically returns the same XML file without the unwanted data.

Regards Ben

2

2 Answers

0
votes

Use this XSLT, it ignores Items which has empty response elements.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

<xsl:template match="Item[normalize-space(response) = '']"/>

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

Output:

<?xml version="1.0" encoding="utf-8"?>
<RepeaterData>
  <Version />
  <Items>
    <Item>

      <response type="System.String">xxx</response>
      <response_date type="System.String" />
      <digital_signature_field_profile_name type="System.String">tester3_Dianne</digital_signature_field_profile_name>
      <approver_role type="System.String">tester3</approver_role>
      <approver_workflow_group type="System.Int32">3</approver_workflow_group>
      <approver_workflow_sequence_in_group type="System.Int32">2</approver_workflow_sequence_in_group>

    </Item>
    <Item>

      <response type="System.String">xxx</response>
      <response_date type="System.String" />
      <digital_signature_field_profile_name type="System.String">tester2_Ben</digital_signature_field_profile_name>
      <approver_role type="System.String">tester2</approver_role>
      <approver_workflow_group type="System.Int32">1</approver_workflow_group>
      <approver_workflow_sequence_in_group type="System.Int32">3</approver_workflow_sequence_in_group>
    </Item>



  </Items>
</RepeaterData>
0
votes

I need to transform an XML file another XML file but filter out some unneeded records. The output XML file needs to have the exact node structure of the input XML file.

This is a common requirement. It is usually solved by starting with an identity transform template to copy everything as is, then adding specific templates to suppress the nodes you wish to exclude.