none
Arrange nodes under elements according to some conditions

    Question

  • The XML document that I have:

    <Area>
         <Type>A</Type>
         <Street>
           <Position>5</Position>
           <House>
    
           --> some elements
    
           </House>
         </Street>
         <Street>
           <Position>5</Position>
           <Block>
    
           --> some elements
    
           </Block>
         </Street>
         <Street>
           <Position>6</Position>
           <House>
    
           --> some elements
    
           </House>
         </Street>
         <Street>
           <Position>6</Position>
           <Block>
    
           --> some elements
    
           </Block>
         </Street>
       </Area>

    And it gets arranged like this:

    <Area>
       <Type>A</Type>
         <Street>
           <Position>5</Position>
           <House>
    
           --> some elements
    
           </House>
           <Block>
    
           --> some elements
    
           </Block>
         </Street>
         <Street>
           <Position>6</Position>
           <House>
    
           --> some elements
    
           </House>
           <Block>
    
           --> some elements
    
           </Block>
         </Street>
       </Area>

    And this is the XSLT code I use:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:strip-space elements="*" />
      <xsl:output method="xml" indent="yes" />
    
      <xsl:key name="streetByPosition" match="Street" use="concat(../Type, '|', Position)" />
    
      <xsl:template match="@*|node()">
        <xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
      </xsl:template>
    
      <!-- for the first Street in each Position -->
      <xsl:template match="Street[generate-id() =
                                generate-id(key('streetByPosition', concat(../Type, '|', Position))[1])]">
        <Street>
          <!-- copy in the Position element once only -->
          <xsl:apply-templates select="Position" />
          <!-- copy in all sub-elements except Position from all matching Streets-->
          <xsl:apply-templates select="
                key('streetByPosition', concat(../Type, '|', Position))/*[not(self::Position)]" />
        </Street>
      </xsl:template>
    
      <!-- ignore all other Street elements -->
      <xsl:template match="Street" />
    </xsl:stylesheet>

    But I got a new requirement, where there is also the element Option under each Block or House, with an attribute. The element can be called either <L Option> or <O Option> but they have the same meaning and function. Just that L Option is under House elements and O Option is underBlock elements. But that is not that important.

    The attribute of this Option element can be either empty (so it will look like <O Option="" LineNr="1">) or have some value a or o (<O Option="a" LineNr="1").

    question:

    So I need to make arrangement according to some conditions. As I have multiple and repetitive positions under the same Type I want to check the value of the Option attribute and if the Option of the first occurrence of a position in a type has value and then all the rest positions with the same number, in this type, have also Option with a value, then I want to arrange them under the header of the upper position. For example:

    *Position__Option*

    5

    5

    6 __ o/a

    6 __ o/a

    6 __ o/a -> Then the elements (Blocks and Houses) under Position 6 will not be arranged together under header "Position 6" but will go together with the 5.

    But if not all of the positions are with Option value, like the scenario:

    *Position__Option*

    5

    5

    6 __ o/a (or no "o/a" value)

    6

    6 __ o/a (or no "o/a" value) -> Then they get arranged as 5 and 6 (so normal arrangement, as the code works now).

    Or if in the certain type there is only one Position number that occurs, but all of the Option attributes have values, like:

    *Position__Option*

    6 __ o/a

    6 __ o/a

    6 __ o/a -> They get arranged in the normal way.

    summary

    So the conditions are: 1. if the first occurrence of the position has a value in its Option and all the rest of this position number under it have also value in the Option - then they get arranged under the upper position number that occurs in the current type.

    1. if all the position occurrences have value in the Option, but there are no other different position numbers in the current type - then they are arranged under the current position number (because there is no other different position number).
    Wednesday, August 14, 2013 10:20 AM