如何使用XSLT将XML转换为表[CODE UPDATED 11/6]

时间:2014-06-10 05:32:09

标签: xml xslt

我有一个XML文件希望通过XSLT转换为表或CSV。我试过Altova MapForce 2014来映射列,但仍然无法产生结果。非常感谢。

我有的XML文件

<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>

预期结果

|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

<?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>

2 个答案:

答案 0 :(得分:0)

这里需要两个嵌套循环:

...
<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>
...

编辑:

为避免将所有名称详细信息存储在各个变量中,您可以执行以下操作:

<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>

编辑2:

以下是3个嵌套循环的示例,添加您在最新编辑中添加的日期。

<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>

答案 1 :(得分:0)

以下是使用模板完成此操作的方法。要增加排列级别的数量,您只需要增加模板的数量,并将越来越多的参数从一个传递到下一个:

<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>