How to use XSLT to convert a simple piece of XML

2019-08-14 03:20发布

问题:

How can you convert

<person>
   <personFirstName>FirstName</personFirstName>
   <personLastName>LastName</personLastName>
   <personAge>40</personAge>
</person>

to

<person>
   <name>
      <first>FirstName</first>
      <last>LastName</last>
   </name>
   <age>40</age>
</person>

using XSLT, moreover, if the input XML is a collection of person nodes, like so:

<persons>
   <person>
       ...
   </person>
</persons>

回答1:

A "push-style" solution:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="personFirstName">
  <name>
   <xsl:apply-templates mode="renameWrapped"
        select=".|../personLastName"/>
  </name>
 </xsl:template>

 <xsl:template match="personFirstName" mode="renameWrapped">
  <first><xsl:apply-templates/></first>
 </xsl:template>

 <xsl:template match="personLastName" mode="renameWrapped">
  <last><xsl:apply-templates/></last>
 </xsl:template>

 <xsl:template match="personAge">
  <age><xsl:apply-templates/></age>
 </xsl:template>
 <xsl:template match="personLastName"/>
</xsl:stylesheet>

when applied on this XML document:

<persons>
    <person>
        <personFirstName>FirstName</personFirstName>
        <personLastName>LastName</personLastName>
        <personAge>40</personAge>
    </person>
    <person>
        <personFirstName>FirstName2</personFirstName>
        <personLastName>LastName2</personLastName>
        <personAge>100</personAge>
    </person>
</persons>

the wanted, correct result is produced:

<persons>
   <person>
      <name>
         <first>FirstName</first>
         <last>LastName</last>
      </name>
      <age>40</age>
   </person>
   <person>
      <name>
         <first>FirstName2</first>
         <last>LastName2</last>
      </name>
      <age>100</age>
   </person>
</persons>

Explanation:

  1. Using and overriding the identity rule/template for wrapping and renaming of elements.

  2. The elements to be wrapped are renamed in mode renameWrapped.

  3. The personAge element is renamed in a non-moded template that overrides the identity rule for elements named personAge.



回答2:

It should be very easy. You can try to:

  • match person then open name, apply templates, close name, open age, get value from personAge, close age
  • match personFirstName, open first, get value, close first
  • same as personFirstName for personLastName

I think 3 templates wihtout loops should be enough. Try it!



回答3:

The key is the identity transform and overriding it when needed.

Sample XML

<persons>
  <person>
    <personFirstName>FirstName</personFirstName>
    <personLastName>LastName</personLastName>
    <personAge>40</personAge>
  </person>
  <person>
    <personFirstName>FirstName2</personFirstName>
    <personLastName>LastName2</personLastName>
    <personAge>100</personAge>
  </person>
</persons>

Sample XSLT

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

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

  <xsl:template match="person">
    <person>
      <name>
        <first><xsl:apply-templates select="personFirstName"/></first>
        <last><xsl:apply-templates select="personLastName"/></last>
      </name>
      <age><xsl:apply-templates select="personAge"/></age>
    </person>
  </xsl:template>

  <xsl:template match="personFirstName|personLastName|personAge">
    <xsl:apply-templates/>
  </xsl:template>

</xsl:stylesheet>

OUTPUT

<persons>
   <person>
      <name>
         <first>FirstName</first>
         <last>LastName</last>
      </name>
      <age>40</age>
   </person>
   <person>
      <name>
         <first>FirstName2</first>
         <last>LastName2</last>
      </name>
      <age>100</age>
   </person>
</persons>


标签: xslt