Merging different complex data using XSLT 1.0 XML

2019-06-06 10:21发布

问题:

   <?xml version="1.0" encoding="windows-1250"?>
    <CONTACTS>
    <CONTACT>
    <Customer-ID>Cus-ID3</Customer-ID>
    <FirstName>Arnaaud</FirstName>
    <LastName>Forestier</LastName>
    <EMail>Arnaaud_Forestier201111@yahoo.fr</EMail>
    </CONTACT>

    <CONTACT>
    <Customer-ID>Cus-ID5</Customer-ID>
    <FirstName>Arun_Forestier</FirstName>
    <LastName>Forestier</LastName>
    <EMail>Arnaaud_Forestier201111@yahoo.fr</EMail>
    <EMail>Arnaaud_Forestier201111@gmail.com</EMail>
    </CONTACT>

    <CONTACT>
    <Customer-ID>Cus-ID7</Customer-ID>
    <FirstName>Aana</FirstName>
    <LastName>Edwards</LastName>
    <EMail>Aana.edwards@gmail.com</EMail>
    </CONTACT>

    <CONTACT>
    <Customer-ID>Cus-ID9</Customer-ID>
    <FirstName>Aana_Edwards</FirstName>
    <LastName>Edwards</LastName>
    <EMail>Aana.edwards@yahoo.com</EMail>
    </CONTACT>

     <CONTACT>
    <Customer-ID>Cus-ID11</Customer-ID>
    <FirstName>Lina</FirstName>
    <LastName>Joseph</LastName>
    <EMail>Lina.Joseph@aol.com</EMail>
    </CONTACT>

   <CONTACT>
    <Customer-ID>Cus-ID13</Customer-ID>
    <FirstName>SandfordFrankie</FirstName>
    <LastName>Frankie Sandford/LastName>
    <EMail>Sandford1233@yahoo.com</EMail>
    <URL>http://www.facebook.com/profile.php?id=122112487211054</URL>
    </CONTACT>

    <CONTACT>
    <Customer-ID>Cus-ID15</Customer-ID>
    <FirstName>Sandford</FirstName>
    <LastName>Frankie/LastName>
    <EMail>Sandford1233@yahoo.com</EMail>
    <EMail>Sandford.frankie@gmail.com</EMail>
    </CONTACT>

</CONTACTS>

The above XML file has some complex data and this question might look similar to this question. Grouping and merging of two contacts in XSLT1.0 According to me this data is entirely different(more complex) from the above question, so i'm creating a new question here.

We see the <Customer-ID>Cus-ID3</Customer-ID> & <Customer-ID>Cus-ID5</Customer-ID> data belongs to the same person because one of his email addess is same. How can I merge these 2 contacts as a single contact?

Another problem, <Customer-ID>Cus-ID7</Customer-ID> & <Customer-ID>Cus-ID9</Customer-ID> also belongs to another person. Here she has two different emails but in both the contatcs, the

FirstName & LastName are same values. How can I merge these 2 contacts as a single contact?

Would it be possible to merge these complex data?

I need an output like this using XSLT-1.0

<?xml version="1.0" encoding="windows-1250"?>
<CONTACTS>
    <CONTACT>
    <Customer-ID>Cus-ID5</Customer-ID>
        <FirstName>Arun_Forestier</FirstName>
        <LastName>Forestier</LastName>
        <EMail>Arnaaud_Forestier201111@yahoo.fr</EMail>
        <EMail>Arnaaud_Forestier201111@gmail.com</EMail>
    </CONTACT>


    <CONTACT>
    <Customer-ID>Cus-ID9</Customer-ID>
        <FirstName>Aana_Edwards</FirstName>
        <LastName>Edwards</LastName>
        <EMail>Aana.edwards@yahoo.com</EMail>
    <EMail>Aana.edwards@gmail.com</EMail>
    </CONTACT>

</CONTACTS>

Please tell me if there is any flaw in my question. Thank you very much. Note: The email address displayed here are duplicate values.

回答1:

As requested, here a stylesheet that works as follows:

  • merges nodes for which at least an EMail is matching
  • during merge, FirstName and SecondName are copied from the first node always
  • nodes with no matching EMail are copied as is
  • nodes without EMail nodes are copied as is

[XSLT 1.0]

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

    <xsl:key name="k_ContactsByEmail"
        match="CONTACTS/CONTACT"
        use="EMail"/>

    <xsl:template match="CONTACTS">
        <xsl:copy>
            <xsl:apply-templates select="CONTACT[generate-id()=
                generate-id(key('k_ContactsByEmail',EMail)[1])]
                |
                CONTACT[not(EMail)]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="CONTACT">
        <xsl:copy>
            <xsl:copy-of select="*"/>
            <xsl:copy-of select="
                key('k_ContactsByEmail', EMail)/*
                    [not(.=current()/*)]
                    [not(self::FirstName or self::LastName or self::Customer-ID)]"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

When applied on the XML input provided in the question, it produces:

<CONTACTS>
   <CONTACT>
      <Customer-ID>Cus-ID3</Customer-ID>
      <FirstName>Arnaaud</FirstName>
      <LastName>Forestier</LastName>
      <EMail>Arnaaud_Forestier201111@yahoo.fr</EMail>
      <EMail>Arnaaud_Forestier201111@gmail.com</EMail>
   </CONTACT>
   <CONTACT>
      <Customer-ID>Cus-ID7</Customer-ID>
      <FirstName>Aana</FirstName>
      <LastName>Edwards</LastName>
      <EMail>Aana.edwards@gmail.com</EMail>
   </CONTACT>
   <CONTACT>
      <Customer-ID>Cus-ID9</Customer-ID>
      <FirstName>Aana_Edwards</FirstName>
      <LastName>Edwards</LastName>
      <EMail>Aana.edwards@yahoo.com</EMail>
   </CONTACT>
   <CONTACT>
      <Customer-ID>Cus-ID11</Customer-ID>
      <FirstName>Lina</FirstName>
      <LastName>Joseph</LastName>
      <EMail>Lina.Joseph@aol.com</EMail>
   </CONTACT>
   <CONTACT>
      <Customer-ID>Cus-ID13</Customer-ID>
      <FirstName>SandfordFrankie</FirstName>
      <LastName>Frankie Sandford</LastName>
      <EMail>Sandford1233@yahoo.com</EMail>
      <URL>http://www.facebook.com/profile.php?id=122112487211054</URL>
      <EMail>Sandford.frankie@gmail.com</EMail>
   </CONTACT>
</CONTACTS>


标签: xml xslt merge