1

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!!

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

That indeed is the prompt, apt and accurate reply!!!!! Could not add your answer up as my id's reputation is too low for that. Thanks a ton man!!!!!!! You saved my day.....

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.