How to use XSLT to convert a XML to Table [CODE UP

2019-03-05 06:31发布

问题:

I have a XML file want to convert to a Table OR CSV by XSLT. I tried by Altova MapForce 2014to map the columns but still,not able to gen out the outcomes. thanks a lot.

XML file I have

<Records>
    <Person id="756252" date="15-Oct-2014">
        <Gender>Male</Gender>
        <NameDetails>
            <Name NameType="Primary Name">
                <NameValue>
                    <FirstName>Ken</FirstName>
                    <Surname>Wu</Surname>
                </NameValue>
            </Name>
            <Name NameType="AKA">
                <NameValue>
                    <FirstName>Kenneth</FirstName>
                    <Surname>Wu</Surname>
                </NameValue>
            </Name>
            <Name NameType="AKA2">
                <NameValue>
                    <FirstName>CAN</FirstName>
                    <Surname>Wu</Surname>
                </NameValue>
            </Name>
        </NameDetails>
        <Descriptions>
            <Description Description1="11" Description2="12" Description3="13"/>
            <Description Description1="21" Description2="22" Description3="23"/>
            <Description Description1="31" Description2="32" Description3="33"/>
        </Descriptions>
        <DateDetails>
        <Date DateType="Date of Birth">
            <DateValue Year="1990" />
            <DateValue Year="1991" />
        </Date>
        <Date DateType="Date of Issue">
            <DateValue Year="2000" />
            <DateValue Year="2001" />
        </Date>
        </DateDetails>
    </Person>
    <Person id="253555" date="14-Oct-2014">
        <Gender>Male</Gender>
        <NameDetails>
            <Name NameType="Primary Name">
                <NameValue>
                    <FirstName>Peter</FirstName>
                    <Surname>Lai</Surname>
                </NameValue>
            </Name>
        </NameDetails>
        <Descriptions>
            <Description Description1="11" Description2="12" Description3="13"/>
            <Description Description1="21" Description2="22"/>
        </Descriptions>
        <Date DateType="Date of Birth">
            <DateValue Year="1992" />
        </Date>
    </Person>
</Records>

expected outcome

|ID     |Date        |Gender |NameType     |FirstName |SurName |Description1 |Description2 |Description3 |DateType      |Year|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |11           |12           |13           |Date of Birth |1990|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |21           |22           |23           |Date of Birth |1990|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |31           |32           |33           |Date of Birth |1990|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |11           |12           |13           |Date of Birth |1990|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |21           |22           |23           |Date of Birth |1990|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |31           |32           |33           |Date of Birth |1990|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |11           |12           |13           |Date of Birth |1990|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |21           |22           |23           |Date of Birth |1990|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |31           |32           |33           |Date of Birth |1990|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |11           |12           |13           |Date of Issue |1991|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |21           |22           |23           |Date of Issue |1991|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |31           |32           |33           |Date of Issue |1991|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |11           |12           |13           |Date of Issue |1991|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |21           |22           |23           |Date of Issue |1991|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |31           |32           |33           |Date of Issue |1991|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |11           |12           |13           |Date of Issue |1991|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |21           |22           |23           |Date of Issue |1991|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |31           |32           |33           |Date of Issue |1991|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |11           |12           |13           |Date of Issue |2000|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |21           |22           |23           |Date of Issue |2000|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |31           |32           |33           |Date of Issue |2000|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |11           |12           |13           |Date of Issue |2000|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |21           |22           |23           |Date of Issue |2000|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |31           |32           |33           |Date of Issue |2000|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |11           |12           |13           |Date of Issue |2000|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |21           |22           |23           |Date of Issue |2000|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |31           |32           |33           |Date of Issue |2000|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |11           |12           |13           |Date of Issue |2001|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |21           |22           |23           |Date of Issue |2001|
|756252 |15-Oct-2014 |Male   |Primary Name |Ken       |Wu      |31           |32           |33           |Date of Issue |2001|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |11           |12           |13           |Date of Issue |2001|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |21           |22           |23           |Date of Issue |2001|
|756252 |15-Oct-2014 |Male   |AKA          |Kenneth   |Wu      |31           |32           |33           |Date of Issue |2001|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |11           |12           |13           |Date of Issue |2001|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |21           |22           |23           |Date of Issue |2001|
|756252 |15-Oct-2014 |Male   |AKA2         |CAN       |Wu      |31           |32           |33           |Date of Issue |2001|
|253555 |14-Oct-2014 |Male   |Primary Name |Peter     |Lai     |11           |12           |13           |Date of Issue |1992|
|253555 |14-Oct-2014 |Male   |Primary Name |Peter     |Lai     |21           |22           |             |Date of Issue |1992|

XSL i create for testing

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <html>
   <head>
    <title>Records</title>
   </head>
   <body>
    <table border="1">
     <tr>
      <th>ID</th>
      <th>date</th>
      <th>Gender</th>
      <th>NameType</th>
      <th>FirstName</th>
      <th>SurName</th>
      <th>Description1</th>
      <th>Description2</th>
      <th>Description3</th>
     </tr>
     <xsl:for-each select="Records/Person/NameDetails/Name">
     <tr>
      <td><xsl:value-of select="../../@id"/></td>
      <td><xsl:value-of select="../../@date"/></td>
      <td><xsl:value-of select="../../Gender"/></td>
      <td><xsl:value-of select="@NameType"/></td>
      <td><xsl:value-of select="NameValue/FirstName"/></td>
      <td><xsl:value-of select="NameValue/Surname"/></td>
      <td><xsl:value-of select="../../Descriptions/Description/@Description1"/></td>
      <td><xsl:value-of select="../../Descriptions/Description/@Description2"/></td>
      <td><xsl:value-of select="../../Descriptions/Description/@Description3"/></td>
     </tr>
     </xsl:for-each>
    </table>
   </body>
  </html>
 </xsl:template>
</xsl:stylesheet>

回答1:

You need two nested loops here:

...
<xsl:for-each select="Records/Person/NameDetails/Name">
    <xsl:variable name="NameType" select="@NameType"/>
    <xsl:variable name="FirstName" select="NameValue/FirstName"/>
    <xsl:variable name="Surname" select="NameValue/Surname"/>
        <xsl:for-each select="../../Descriptions/Description">
            <tr>
                <td><xsl:value-of select="../../@id"/></td>
                <td><xsl:value-of select="../../@date"/></td>
                <td><xsl:value-of select="../../Gender"/></td>
                <td><xsl:value-of select="$NameType"/></td>
                <td><xsl:value-of select="$FirstName"/></td>
                <td><xsl:value-of select="$Surname"/></td>
                <td><xsl:value-of select="@Description1"/></td>
                <td><xsl:value-of select="@Description2"/></td>
                <td><xsl:value-of select="@Description3"/></td>
            </tr>
        </xsl:for-each>
</xsl:for-each>
...

Edit:

To avoid storing all name details in individual variables, you can do:

<xsl:for-each select="Records/Person/NameDetails/Name">
    <xsl:variable name="name" select="."/>
    <xsl:for-each select="../../Descriptions/Description">
        <tr>
            <td><xsl:value-of select="../../@id"/></td>
            <td><xsl:value-of select="../../@date"/></td>
            <td><xsl:value-of select="../../Gender"/></td>
            <td><xsl:value-of select="$name/@NameType"/></td>
            <td><xsl:value-of select="$name/NameValue/FirstName"/></td>
            <td><xsl:value-of select="$name/NameValue/Surname"/></td>
            <td><xsl:value-of select="@Description1"/></td>
            <td><xsl:value-of select="@Description2"/></td>
            <td><xsl:value-of select="@Description3"/></td>
        </tr>
    </xsl:for-each>
</xsl:for-each>

Edit 2:

Here's an example of 3 nested loops, adding the dates you have added in your latest edit.

<xsl:for-each select="Records/Person/NameDetails/Name">
    <xsl:variable name="name" select="."/>
    <xsl:for-each select="../../DateDetails/Date/DateValue">
        <xsl:variable name="dateval" select="."/>
        <xsl:for-each select="../../../Descriptions/Description">
            <tr>
                <td><xsl:value-of select="../../@id"/></td>
                <td><xsl:value-of select="../../@date"/></td>
                <td><xsl:value-of select="../../Gender"/></td>
                <td><xsl:value-of select="$name/@NameType"/></td>
                <td><xsl:value-of select="$name/NameValue/FirstName"/></td>
                <td><xsl:value-of select="$name/NameValue/Surname"/></td>
                <td><xsl:value-of select="@Description1"/></td>
                <td><xsl:value-of select="@Description2"/></td>
                <td><xsl:value-of select="@Description3"/></td>
                <td><xsl:value-of select="$dateval/../@DateType"/></td>
                <td><xsl:value-of select="$dateval/@Year"/></td>
            </tr>
        </xsl:for-each>
    </xsl:for-each>
</xsl:for-each>


回答2:

Here's how you can accomplish this using templates. To increase the number of levels of permutations, you'll just need to increase the number of templates, and pass more and more parameters from one to the next:

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

  <xsl:template match="/*">
    <html>
      <head>
        <title>Records</title>
      </head>
      <body>
        <table border="1">
          <tr>
            <th>ID</th>
            <th>date</th>
            <th>Gender</th>
            <th>NameType</th>
            <th>FirstName</th>
            <th>SurName</th>
            <th>Description1</th>
            <th>Description2</th>
            <th>Description3</th>
            <th>DateType</th>
            <th>Year</th>
          </tr>
          <xsl:apply-templates select="Person" />
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="Person">
    <xsl:apply-templates select=".//Date/DateValue" />
  </xsl:template>

  <xsl:template match="DateValue">
    <xsl:apply-templates select="ancestor::Person/NameDetails/Name">
      <xsl:with-param name="date" select="." />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="Name">
    <xsl:param name="date" select="/.." />

    <xsl:apply-templates select="ancestor::Person/Descriptions/Description">
      <xsl:with-param name="date" select="$date" />
      <xsl:with-param name="name" select="." />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="Description">
    <xsl:param name="date" select="/.." />
    <xsl:param name="name" select="/.." />

    <tr>
      <td>
        <xsl:value-of select="../../@id"/>
      </td>
      <td>
        <xsl:value-of select="../../@date"/>
      </td>
      <td>
        <xsl:value-of select="../../Gender"/>
      </td>
      <td>
        <xsl:value-of select="$name/@NameType"/>
      </td>
      <td>
        <xsl:value-of select="$name/NameValue/FirstName"/>
      </td>
      <td>
        <xsl:value-of select="$name/NameValue/Surname"/>
      </td>
      <td>
        <xsl:value-of select="@Description1"/>
      </td>
      <td>
        <xsl:value-of select="@Description2"/>
      </td>
      <td>
        <xsl:value-of select="@Description3"/>
      </td>
      <td>
        <xsl:value-of select="$date/../@DateType"/>
      </td>
      <td>
        <xsl:value-of select="$date/@Year"/>
      </td>
    </tr>
  </xsl:template>
</xsl:stylesheet>


标签: xml xslt