在一个XSLT文档中组合两个XML文档并匹配值

时间:2012-11-19 22:50:15

标签: php xslt xslt-1.0

我有两个具有不同结构的XML文档(下面的示例),我想在我用于创建HTML输出的XSLT文档中合并。

我想要做的是创建一个这样的表(汽车示例):

Serialnr    Brand    Color    Year    Price    Condition
 123456     'Opel'   'Blue'   '1978'  '10000$'   'Used'
  ...        ...      ...      ...     ...      ...

最后两个(价格和条件)可以在第二个文档(foo2.xml)中找到,这些文档之间的匹配是serialnr。汽车没有在文件中以相同的顺序排序,并且在foo2.xml(不会被使用)中存在比foo1.xml中更多的汽车。

foo1.xml:

<cars>
    <car>
        <serialnr>123456</serialnr>
        <brand>Opel</brand>
        <color>Blue</color>
        <year>1978</year>
    </car>
    ...and so on...

foo2.xml:

<vehicles>
    <vehicle>
        <cell nr="2"><data nr="3">123456</data></vehicle> // <--- match on serialnr (123456)
        <cell><data nr="3">10000$</data></cell>
        <cell><data nr="3">Used</data></cell>
    ...and so on...

Foo1.xml在服务器端使用PHP连接到XSLT文档,并且在XSLT文档中合并了foo2.xml(见下文)。

cars.xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">

    <xsl:param name="foo2" select="'foo2.xml'"/>

    <xsl:template match="/">

        <xsl:text disable-output-escaping='yes'>&lt;!DOCTYPE html></xsl:text>

        <html>
            <head>
                <title>Producers</title>
            </head>
            <body>
                       ...//table, thead, tr, th...

                    <tbody>
                        <xsl:for-each select="//car">
                        <tr>
                            <td>
                                <xsl:value-of select="serialnr" />
                            </td>
                            <td>
                                <xsl:value-of select="brand" />
                            </td>
                            <td>
                                <xsl:value-of select="color" />
                            </td>
                            <td>
                                <xsl:value-of select="year" />
                            </td>
                          </xsl:for-each>
                          <xsl:for-each select="document($foo2)//Vehicle">
                               // I need to match the serialnr in some way to get the correct car's data here, but how?
                               <td>
                                    // Selecting Cell node 2 (price)
                                    //<xsl:value-of select="/? "/>
                               </td>
                               <td>
                                    // Selecting Cell node 3 (condition)
                                    //<xsl:value-of select="/? "/>
                               </td>

那么,我该怎么做呢?我非常感谢这里的帮助。非常感谢提前!

注意:

  1. foo2.xml的结构不一致。突然,子节点从“车辆”变为“部分”(即“车辆/车辆”变为“车辆/部件”)。
  2. 在foo2.xml中有很多“车辆”节点包含我不感兴趣的数据,所以我想我必须使用某种if语句来测试循环时是否存在所需的数据它们?

1 个答案:

答案 0 :(得分:1)

猜测我在主评论Feed中发布的问题的答案,请找到这个XSLT 1.0解决方案。

以此文件为主要输入......

<cars>
   <car>
        <serialnr>123456</serialnr>
        <brand>Opel</brand>
        <color>Blue</color>
        <year>1978</year>
  </car>
   <car>
        <serialnr>789</serialnr>
        <brand>Toyota</brand>
        <color>Beige</color>
        <year>2005</year>
  </car>
</cars>  

...此文档作为可读文档资源传入样式表,参数名称为foo2 ...

<vehicles>
  <vehicle>
    <cell><data>123456</data></cell>
    <cell><data>10000$</data></cell>
    <cell><data>Used</data></cell>
  </vehicle>
  <vehicle>
    <cell><data>789</data></cell>
    <cell><data>20000$</data></cell>
    <cell><data>Pre-loved</data></cell>
  </vehicle>

...这个XSLT 1.0样式表... *

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />  

<xsl:param name="foo2" select="'foo2.xml'" />
<xsl:variable name="vehicles" select="document($foo2)/vehicles/vehicle" />

<xsl:template match="/">
 <html lang="en">
   <head><title>Cars</title></head>
   <body>  
     <xsl:apply-templates select="cars" />
   </body>  
 </html>
</xsl:template>

<xsl:template match="cars">
  <table>
    <th>
      <td>Serialnr</td> <td>Brand</td> <td>Color</td> <td>Year</td> <td>Price</td> <td>Condition</td>
    </th>
    <xsl:apply-templates select="car" />
  </table>
</xsl:template>

<xsl:template match="car">
  <xsl:variable name="srl" select="serialnr/text()" />
    <tr>
      <td><xsl:value-of select="$srl" /></td>
      <td><xsl:value-of select="brand" /></td>
      <td><xsl:value-of select="color" /></td>
      <td><xsl:value-of select="year" /></td>
      <td><xsl:value-of select="$vehicles/self::*[cell/data=$srl]/cell[2]" /></td>
      <td><xsl:value-of select="$vehicles/self::*[cell/data=$srl]/cell[3]" /></td>
    </tr>
</xsl:template>

</xsl:stylesheet>

...将产生此输出(HTML5文档)...

<!DOCTYPE html SYSTEM "about:legacy-compat">
<html lang="en">
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Cars</title>
  </head>
  <body>
    <table>
      <th>
        <td>Serialnr</td>
        <td>Brand</td>
        <td>Color</td>
        <td>Year</td>
        <td>Price</td>
        <td>Condition</td>
      </th>
      <tr>
        <td>123456</td>
        <td>Opel</td>
        <td>Blue</td>
        <td>1978</td>
        <td>10000$</td>
        <td>Used</td>
      </tr>
      <tr>
        <td>789</td>
        <td>Toyota</td>
        <td>Beige</td>
        <td>2005</td>
        <td>20000$</td>
        <td>Pre-loved</td>
      </tr>
    </table>
  </body>
</html>

注意

使用密钥的解决方案也是可能的。