Adi
Adi

Reputation: 123

adjusting duplicates IN XML using xslt

I'm having an xml as below:

<?xml version="1.0" encoding="utf-8"?><Master>
<Account ID="38058226">
    <Property ID="66591454">
        <Profile ID="111234">\Acct_38058226\Prop_66591454\Prof_111234.xml</Profile>
    </Property>
</Account>
<Account ID="38058226">
    <Property ID="66591454">
        <Profile ID="22222222222">\Acct_38058226\Prop_66591454\Prof_22222222222.xml</Profile>
    </Property>
</Account>
<Account ID="38058226">
    <Property ID="66591455">
        <Profile ID="000000">\Acct_38058226\Prop_66591454\Prof_000000.xml</Profile>
    </Property>
</Account>
<Account ID="38058227">
    <Property ID="66591454">
        <Profile ID="000000">\Acct_38058226\Prop_66591454\Prof_000000.xml</Profile>
    </Property>
</Account>
</Master>

The output I'm looking for is:

<Master>
<Account ID="38058226">
    <Property ID="66591454">
        <Profile ID="111234">\Acct_38058226\Prop_66591454\Prof_111234.xml</Profile>
        <Profile ID="22222222222">\Acct_38058226\Prop_66591454\Prof_22222222222.xml</Profile>
    </Property>
    <Property ID="66591455">
        <Profile ID="000000">\Acct_38058226\Prop_66591454\Prof_000000.xml</Profile>
    </Property>
</Account>
<Account ID="38058227">
    <Property ID="66591454">
        <Profile ID="000000">\Acct_38058226\Prop_66591454\Prof_000000.xml</Profile>
    </Property>
</Account>
</Master>

I'm using XSLT 1.0. The xml keeps on expanding every night. I'm very new to xml/xslt. I spent hours in my hand in studying it but the delivery is very near and hence seeking the help. The hint which I got is that I might have to use the Muenchian Grouping, forming the keys and grouping. I'm still learning and not able to create the logic for myself yet. Thanks in advance!!

Upvotes: 1

Views: 56

Answers (1)

ABach
ABach

Reputation: 3738

Here's one way to do it.

When this XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key 
    name="kAccounts"
    match="Account"
    use="@ID"/>
  <xsl:key
    name="kPropertiesByAccount"
    match="Property"
    use="parent::Account/@ID"/>
  <xsl:key
    name="kPropertiesByIdAndAccount"
    match="Property"
    use="concat(@ID, '+', parent::Account/@ID)"/>
  <xsl:key
    name="kProfileByPropertyAndAccount"
    match="Profile"
    use="concat(parent::Property/@ID, '+', ancestor::Account/@ID)"/>

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

  <xsl:template match="/*">
    <Master>
      <xsl:apply-templates
        select="Account[
          generate-id() = generate-id(key('kAccounts', @ID)[1])
        ]"/>
    </Master>

  </xsl:template>

  <xsl:template match="Account">
    <xsl:copy>
      <xsl:apply-templates
        select="@*|key(
          'kPropertiesByAccount', @ID)[
            generate-id() =
            generate-id(
              key('kPropertiesByIdAndAccount',
                concat(@ID, '+', parent::Account/@ID))[1])
          ]"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="Property">
    <xsl:copy>
      <xsl:apply-templates
        select="@*|key(
          'kProfileByPropertyAndAccount',
           concat(@ID, '+', parent::Account/@ID))"/>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

...is run against the provided XML:

<?xml version="1.0" encoding="UTF-8"?>
<Master>
  <Account ID="38058226">
    <Property ID="66591454">
      <Profile ID="111234">\Acct_38058226\Prop_66591454\Prof_111234.xml</Profile>
    </Property>
  </Account>
  <Account ID="38058226">
    <Property ID="66591454">
      <Profile ID="22222222222">\Acct_38058226\Prop_66591454\Prof_22222222222.xml</Profile>
    </Property>
  </Account>
  <Account ID="38058226">
    <Property ID="66591455">
      <Profile ID="000000">\Acct_38058226\Prop_66591454\Prof_000000.xml</Profile>
    </Property>
  </Account>
  <Account ID="38058227">
    <Property ID="66591454">
      <Profile ID="000000">\Acct_38058226\Prop_66591454\Prof_000000.xml</Profile>
    </Property>
  </Account>
</Master>

...the wanted result is produced:

<Master>
  <Account ID="38058226">
    <Property ID="66591454">
      <Profile ID="111234">\Acct_38058226\Prop_66591454\Prof_111234.xml</Profile>
      <Profile ID="22222222222">\Acct_38058226\Prop_66591454\Prof_22222222222.xml</Profile>
    </Property>
    <Property ID="66591455">
      <Profile ID="000000">\Acct_38058226\Prop_66591454\Prof_000000.xml</Profile>
    </Property>
  </Account>
  <Account ID="38058227">
    <Property ID="66591454">
      <Profile ID="000000">\Acct_38058226\Prop_66591454\Prof_000000.xml</Profile>
    </Property>
  </Account>
</Master>

Note that Muenchian Grouping (as evidenced by the use of <xsl:key> and generate-id()) is, indeed, the way to go.

Upvotes: 2

Related Questions