-1

I need to merge the two nodes street as they have the same:

  • father node: city NEW YORK
  • same method: modify
  • same id: 0

Attributes values must be merged (See the output file at the end of this post)

Here is the input file:

<country>
<state id="NEW JERSEY">
    <city id="NEW YORK">
     <district id="BRONX" method="modify">

        <street id="0" method="modify">
           <attributes>
              <temperature>98</temperature>
              <altitude>1300</altitude>
           </attributes>
        </street>

        <dadada id="99" method="modify" />

        <street id="0" method="modify">
           <attributes>
              <temperature>80</temperature>
              <streetnumber> 67 </streetnumber>
           </attributes>
        </street>

        <dididi id="432" method="modify" />

     </district>


  </city>

</state>

Expected output:

<country>
<state id="NEW JERSEY">
    <city id="NEW YORK">
     <district id="BRONX" method="modify">

        <street id="0" method="modify">
           <attributes>
              <temperature>80</temperature>
              <altitude>1300</altitude>
              <streetnumber> 67 </streetnumber>
           </attributes>
        </street>

        <dadada id="99" method="modify" />

        <dididi id="432" method="modify" />

     </district>

  </city>

</state>
</country>

Please help, I am just beginning XSLT

laurentngu
  • 357
  • 2
  • 13
  • 1
    Posting essentially the same question twice is not the way to increase your chances of getting good answers to your question here on SO. possible duplicate of [how to merge two nodes having "the same father" and adequate method (using XSLT)?](http://stackoverflow.com/questions/11425963/how-to-merge-two-nodes-having-the-same-father-and-adequate-method-using-xslt) – High Performance Mark Jul 11 '12 at 06:04
  • The questions are (slightly) different, although they look very similar. Input files format is definitely different. The other question has a condition on the method (CREATE then MODIFY and id = "MANHATTAN"). Here it is method (MODIFY + MODIFY) and id="0" (number) – laurentngu Jul 11 '12 at 08:24
  • @laurentngu: The fact that you (I suspect you are the same physical person as John) have been asking numerous slight variations of the same question for many months -- shows that you fail to learn from the answers and that you have a deeper problem that is most likely lack of basic understanding of XSLT. I strongly recommend that you get a good book on XSLT and read and learn. There is obviously no benefit for you from keeping posting the same question and obviously not understanding the answers. – Dimitre Novatchev Jul 11 '12 at 12:39
  • @dimetre Novatchev hello, I am not that person/user. I have been asking one time help about xslt tonight as I try to move from Perl to xslt to sort my xml file. That user you mention is a casual remote participant/helper to my personal project. To make it short, I am really eager to learn xslt and propagate it in future projects. I am sorry for the inconvenience that my tonight question is making a recall to other posts, but here is a will to use and learn xslt – laurentngu Jul 11 '12 at 14:50
  • @laurentngu: I have been seeing this question with slight variations since February. Please, stop asking variations of the same question -- it is perfectly possible and even better for your learning, if you ask different questions. – Dimitre Novatchev Jul 11 '12 at 16:18

1 Answers1

1

I have assumed that you are interested in an XSLT 2.0, because that is how you have tagged your question. Let me know if you need the XSLT 1.0 equivalent. This XSLT 2.0 style-sheet should do the trick ...

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

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

<xsl:template match="*[street]">
  <xsl:copy>
   <xsl:apply-templates select="@*"/>
   <xsl:for-each-group select="street" group-by="@method">
    <xsl:apply-templates select="current-group()[1]" />
   </xsl:for-each-group>
   <xsl:apply-templates select="node()[not(self::street)]"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="street/attributes">
 <xsl:copy>
  <xsl:apply-templates select="@*"/>
   <xsl:variable name="grouped-method" select="../@method" />  
   <xsl:for-each-group select="../../street[@method=$grouped-method]/attributes/*" group-by="name()">
    <xsl:apply-templates select="current-group()[1]" />
   </xsl:for-each-group>    
  <xsl:apply-templates select="comment()|processing-instruction()"/>
 </xsl:copy>
</xsl:template>

</xsl:stylesheet> 

Explanation

The second template, matching on elements which are parents of streets, will group the child streets by common method. For each group, only the first street in the group is copied. The rest are dropped.

When this first street of the group is having its 'attributes' node process in the third template, we merge all the attributes from the same group. Possibly 'attributes' is an unfortunate element name in an XML document! This grouping is achieved by looking at all the 'attributes' child nodes of all the allied streets which have the same street parent (Bronx district) and grouping by element name. If there are multiple elements in such a group, just take the values from the first one.

I'm not sure that this is exactly what you want because although the street attributes are merged by 'father' node (Bronx), they are not merged at the city level. This reflects the ambiguity in your question. The 'father' node of streets in your sample date is district not city. If I have got this wrong, and you want grouping at the city level, please clarify and update your question.

Sean B. Durkin
  • 12,659
  • 1
  • 36
  • 65
  • thank you ! Yes I need the (street) merge by 'father node Bronx' (district). So your transformation is working fine, except that it returns `98` instead of `80`. How do you modify the xslt to take the values from the second street (latest value) ? – laurentngu Jul 11 '12 at 11:22
  • Sean, be aware that this user (I believe the same person as John) has been asking variations of the same questions for many months -- you may become *furious* the third time you see the same question with minor variation again and again... :) – Dimitre Novatchev Jul 11 '12 at 12:35
  • @DimitreNovatchev see the explanation above – laurentngu Jul 11 '12 at 15:12
  • replace in the last block `` by `` – laurentngu Jul 12 '12 at 01:47