如何在XML转换中关联不同类型的节点

时间:2018-10-11 00:27:47

标签: xml xslt xpath xslt-1.0

在一个xml文件中,我有两种不同类型的节点(模型和颜色),如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="fwHtml.xsl"?>
<vehicle xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <model>
        <modelID>508560-003</modelID>
        <modelName>Compact</modelName>
        <paintID>511258-008</paintID>
    </model>
    <model>
        <modelID>210588-003</modelID>
        <modelName>Convertible</modelName>
        <paintID>511354-001</paintID>
      <paintID>511353-003</paintID>
    </model>
    <model>
        <modelID>210588-004</modelID>
        <modelName>SUV</modelName>
        <paintID>511354-001</paintID>
        <paintID>511353-004</paintID>
    </model>
    <model>
        <modelID>209545-001</modelID>
        <modelName>Pickup</modelName>
        <paintID>511231-000</paintID>
        <paintID>511232-001</paintID>
    </model>

    <color>
        <paintID>511354-001</paintID>
        <paintName>White</paintName>
        <paintVersion>151.1002</paintVersion>
    </color>
    <color>
        <paintID>511353-003</paintID>
        <paintName>Blue</paintName>
        <paintVersion>152.1002</paintVersion>
    </color>
    <color>
        <paintID>511353-004</paintID>
        <paintName>Brown</paintName>
        <paintVersion>152.1002</paintVersion>
    </color>
    <color>
        <paintID>511258-008</paintID>
        <paintName>Black</paintName>
        <paintVersion>152.1013</paintVersion>
    </color>
    <color>
        <paintID>511231-000</paintID>
        <paintName>Gray</paintName>
        <paintVersion>200.1003</paintVersion>
    </color>
    <color>
        <paintID>511232-001</paintID>
        <paintName>Red</paintName>
        <paintVersion>101.1012</paintVersion>
    </color>
</vehicle>

我正在尝试通过XML转换为每个模型生成可用颜色选项的列表,该图像应类似于下图:

Desired Output

我将以下内容用于xml转换:

<?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>
  <body>
  <h2>Released Paint Versions</h2>
  <table border="1">
    <tr bgcolor="#56a0d3">
      <th>Model ID</th>
      <th>Model Description</th>
      <th>Paint ID</th>
      <th>Paint Description</th>
    </tr>
    <xsl:for-each select="vehicle/model">
      <xsl:for-each select="paintID">
         <tr>
         <td><xsl:value-of select="../modelID"/></td>
         <td><xsl:value-of select="../modelName"/></td>
         <td><xsl:value-of select="."/></td>

         <xsl:for-each select="/vehicle/color">
            <xsl:if test="contains(./paintID,5113)">
              <td><xsl:value-of select="./paintName"/></td>
            </xsl:if>
         </xsl:for-each>

         </tr>
      </xsl:for-each>
    </xsl:for-each>
  </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet> 

这使我很接近,但是我无法弄清楚如何在模型节点中的paintID元素与颜色节点中的paintID元素之间建立关系,因此我得出以下结论,而这并不是我所需要的:

Wrong but close output

<xsl:if test="contains(./paintID,5113)">

这行显然是不对的,但这是我最近来弄清楚如何创建模型/ paintID <->颜色/ paintID关系的

2 个答案:

答案 0 :(得分:1)

在您的paintID循环中,将电流存储在变量中,如下所示:

<xsl:variable name="curr_ID" select="."/>

然后,将您的条件更改为:

<xsl:if test="paintID=$curr_ID">

修改后的样式表如下:

<?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>
            <body>
                <h2>Released Paint Versions</h2>
                <table border="1">
                    <tr bgcolor="#56a0d3">
                        <th>Model ID</th>
                        <th>Model Description</th>
                        <th>Paint ID</th>
                        <th>Paint Description</th>
                    </tr>
                    <xsl:for-each select="vehicle/model">
                        <xsl:for-each select="paintID">
                            <xsl:variable name="curr_ID" select="."/>
                            <tr>
                                <td><xsl:value-of select="../modelID"/></td>
                                <td><xsl:value-of select="../modelName"/></td>
                                <td><xsl:value-of select="."/></td>

                                <xsl:for-each select="/vehicle/color">
                                    <xsl:if test="paintID=$curr_ID">
                                        <td><xsl:value-of select="./paintName"/></td>
                                    </xsl:if>
                                </xsl:for-each>

                            </tr>
                        </xsl:for-each>
                    </xsl:for-each>
                </table>
            </body>
        </html>
    </xsl:template>

</xsl:stylesheet> 

答案 1 :(得分:1)

我会使用xsl:key和'key'函数,这样会更高效:

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

  <xsl:key name="color" match="color" use="paintID"/>

  <xsl:template match="/">
    <html>
      <body>
        <h2>Released Paint Versions</h2>
        <table border="1">
          <tr bgcolor="#56a0d3">
            <th>Model ID</th>
            <th>Model Description</th>
            <th>Paint ID</th>
            <th>Paint Description</th>
          </tr>
          <xsl:apply-templates select="vehicle/model/paintID"/>
        </table>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="paintID">
    <tr>
      <td>
        <xsl:value-of select="../modelID"/>
      </td>
      <td>
        <xsl:value-of select="../modelName"/>
      </td>
      <td>
        <xsl:value-of select="."/>
      </td>
      <td>
        <xsl:value-of select="key('color', .)/paintName"/>
      </td>
    </tr>
  </xsl:template>

</xsl:stylesheet>