简体   繁体   中英

Make multiple changes with XLST 1.0 (uppercase element first letter, order elements, aggrate/group elements)

My input xml looks something like this:

<myFamily>
  <spouse type="1">Halle Berry</spouse>
  <parent type="bio">Jane Smith-Doe</parent>
  <spouse type="2">Eva Longoria</spouse>
  <uncle type="paternal">Bob Beam</uncle>
  <parent type="bio">Jim Beam</parent>
  <uncle type="maternal">Mike Smith</uncle>
  <aunt type="paternal">Viola Davis</aunt>
  <inLaw type="mother">Dr. Curry-Pepper</inLaw>
  <brother name="Ron Isley">
    <child>Sara Isley</child>
    <child>Ron Isley Jr.</child>
    <child>Martha Isley-Focker</child>
  </brother>
  <parent type="step">Jon Doe</parent>
  <inLaw type="father">Dr. Pepper</inLaw>
  <spouse type="3">Sofia Vergara</spouse>
  <uncle type="paternal">Bo Beam</uncle>
  <spouse type="3">Sonya Curry</spouse>
  <Sister name ="Shelly Isley"/>
</myFamily>

I want it to end up like this:

<MyFamily>
  <Parents>
    <Parent type="bio">Jane Smith-Doe</Parent>
    <Parent type="bio">Jim Beam</Parent>
    <Parent type="step">Jon Doe</Parent>
  </Parents>
  <Siblings>
    <Sister name ="Shelly Isley"/>
    <Brother name="Ron Isley">
      <Child>Sara Isley</Child>
      <Child>Ron Isley Jr.</Child>
      <Child>Martha Isley-Focker</Child>
    </Brother>
  <Siblings>
  <Uncles>
    <Uncle type="paternal">Bob Beam</Uncle>
    <Uncle type="maternal">Mike Smith</Uncle>
    <Uncle type="paternal">Bo Beam</Uncle>  
  </Uncles>
  <Aunts><Aunt type="paternal">Viola Davis</Aunt><Aunts>
  <InLaws>
    <InLaw type="mother">Dr. Curry-Pepper</InLaw>
    <InLaw type="father">Dr. Pepper</InLaw>
  </InLaws>
  <Wives>
    <Wife type="1">Halle Berry</Wife>
    <Wife type="2">Eva Longoria</Wife>
    <Wife type="3">Sofia Vergara</Wife>
    <Wife type="3">Sonya Curry</Wife>
  </Wives>
</MyFamily>

To make the first letter uppercase, rename the spouse, and have it ordered a certain way I tried this and it didn't work:

<xsl:template match="@*|node()">
    <xsl:copy>
        <!-- Order Section Nodes -->
        <xsl:apply-templates select="myFamily[(SectionName = 'parent')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'sister')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'brother')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'unle')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'aunt')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'inLaw')]" mode="nodeCopy"/>
        <xsl:apply-templates select="myFamily[(SectionName = 'spouse')]" mode="nodeCopy"/>
        <!-- List All Remaining Nodes and Remove ones that have already been ordered above -->
        <xsl:apply-templates select="@*|node()[not(parent | sister | brother |  spouse | uncle | aunt | inLaw)]"/>
  </xsl:copy>
</xsl:template>
<!-- Rename spouse Nodes -->
<xsl:template match="spouse">
  <Wife><xsl:apply-templates select="@*|node()" mode="nodeCopy"/></Wife>
</xsl:template>
<!-- Uppercase first letter of elements -->
<xsl:template match="*">
  <xsl:element name="{concat(
                        translate(subsstring(name(.),1,1), $vLower, $vUpper),
                        substring(name(.), 2, string-length(name(.))-1)
                      )}">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:element>
</xsl:template>

With regards to the way I want to group it, I feel like this might apply ( https://stackoverflow.com/a/16818842/5517100 ), but I don't understand it. Honestly, I barely understand any of it.

With pre-defined groups as shown in your example, you could do simply:

<xsl:template match="/myFamily">
    <MyFamily>
        <Parents>
            <xsl:apply-templates select="parent"/>
        </Parents>
        <Siblings>
            <xsl:apply-templates select="brother | sister"/>
        </Siblings>
        
        <!-- continue for other groups -->
        
    </MyFamily>
</xsl:template>

Or, if you prefer to omit empty groups:

<xsl:template match="/myFamily">
    <MyFamily>
        <xsl:variable name="parents" select="parent" />
        <xsl:if test="$parents">
            <Parents>
                <xsl:apply-templates select="$parents"/>
            </Parents>
        </xsl:if>
        
        <!-- continue for other groups -->
        
    </MyFamily>
</xsl:template>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM