Получение данных от братьев и сестер на узел, где данные равны данным другого узла

Я работаю с двумя документами XML в одном документе XSLT и пытаюсь объединить данные для помещения в один документ HTML.

Документы совпадают по одной точке, идентификатору. Идентификатор должен быть найден как атрибут для автомобильного узла в foo1.xml. Что касается foo2.xml, идентификатор можно найти внутри узла Data, который является дочерним по отношению к первому узлу Cell (который является дочерним по отношению к узлу Row). Узлы ячейки, следующие за этим первым узлом ячейки, содержат узлы данных, которые содержат требуемые данные (цвет и состояние).

Когда в документе XSLT данные добавляются в ячейки td, мне (каким-то образом) необходимо найти правильный идентификатор в файле foo2.xml и указать цвет и состояние автомобиля в последних двух td.

В документе XSLT ниже вы можете увидеть мою неудачную попытку сделать это. Итак, как это можно сделать?

Заранее большое спасибо!

Примечание. Порядок идентификаторов не совпадает в двух файлах.

foo1.xml:

<cars>
  <car id="8">
    <brand>Saab</brand>
    <model>95</model>
    <year>2011</year>
  </car>
  <car id="57">
    <brand>Chrysler</brand>
    <model>Voyager</model>
    <year>2010</year>
  </cars>
  ...

foo2.xml:

<Table ss:ExpandedColumnCount="5" ss:ExpandedRowCount="79" x:FullColumns="1"
   x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="15">
   <Column ss:Index="2" ss:AutoFitWidth="0" ss:Width="43"/>
   <Column ss:AutoFitWidth="0" ss:Width="113"/>
   <Column ss:Index="5" ss:AutoFitWidth="0" ss:Width="220"/>
   <Row ss:Index="6">
    <Cell ss:Index="3" ss:StyleID="s62"/>
   </Row>
   <Row>
    <Cell ss:Index="3" ss:StyleID="s62"/>
   </Row>
   <Row>
    <Cell ss:Index="3" ss:StyleID="s62"/>
   </Row>
   <Row>
    <Cell ss:Index="2"><Data ss:Type="String">57</Data></Cell>    // <-- where the id is to be found
    <Cell ss:StyleID="s62"><Data ss:Type="String">Yellow</Data></Cell>
    <Cell><Data ss:Type="String">New</Data></Cell>
   </Row>
   <Row>
    <Cell ss:Index="2"><Data ss:Type="Number">8</Data></Cell>    // <-- where the id is to be found
    <Cell ss:StyleID="s62"><Data ss:Type="Number">Black</Data></Cell>
    <Cell><Data ss:Type="Number">Used</Data></Cell>
   </Row>
   <Row>
    <Cell ss:Index="2"><Data ss:Type="Number">25</Data></Cell>    // <-- where the id is to be found
    <Cell ss:StyleID="s62"><Data ss:Type="Number">Blue</Data></Cell>
    <Cell><Data ss:Type="Number">Used</Data></Cell>
   </Row>
   ...

merge.xsl:

   <- declarations... ->
         xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" >   <-- the XML namespace (ss:)

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

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

    <xsl:template match="cars">

    <xsl:for-each select="$foo2//ss:Row">
        <xsl:value-of select="ss:Cell/ss:Data/text()" />
    </xsl:for-each>

    <table>
        <tr>
            <th>Id</th> <th>Brand</th> <th>Model</th> <th>Year</th> <th>Color</th> <th>Condition</th>
        </tr>
        <xsl:apply-templates select="car" />
    </table>
    </xsl:template>

    <xsl:template match="car">
        <xsl:variable name="id" select="data[2]/text()" />
            <tr>
                <td><xsl:value-of select="@id" /></td>
                <td><xsl:value-of select="brand" /></td>
                <td><xsl:value-of select="model" /></td>
                <td><xsl:value-of select="year" /></td>

                <td><xsl:value-of select="$positions//ss:Row/ss:Cell/ss:Data=@id/preceding-sibling::ss:Cell" /></td> <-- failed try (color)
                <td> ??? (Condition) </td>
            </tr>
    </xsl:template>
</xsl:stylesheet>

1 ответ

Решение

Это преобразование:

<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:key name="kRowById" match="Row" use="Cell[1]/Data"/>

 <xsl:variable name="vDoc2" select="document('file:///c:/temp/delete/foo2.xml')"/>

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

 <xsl:template match="car">
  <xsl:variable name="vId" select="@id"/>
  <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     <xsl:for-each select="$vDoc2">
       <color><xsl:value-of select="key('kRowById', $vId)/Cell[2]/Data"/></color>
       <condition><xsl:value-of select="key('kRowById', $vId)/Cell[3]/Data"/></condition>
     </xsl:for-each>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

применительно к предоставленной foo1.xml документ:

<cars>
    <car id="8">
        <brand>Saab</brand>
        <model>95</model>
        <year>2011</year>
    </car>
    <car id="57">
        <brand>Chrysler</brand>
        <model>Voyager</model>
        <year>2010</year>
    </car>
</cars>

и имея при условии foo2.xml документ, расположенный по адресу: c:\temp\delete :

    <Table xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
       xmlns:x="some:x"
       ss:ExpandedColumnCount="5" ss:ExpandedRowCount="79" x:FullColumns="1"
       x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="15">
       <Column ss:Index="2" ss:AutoFitWidth="0" ss:Width="43"/>
       <Column ss:AutoFitWidth="0" ss:Width="113"/>
       <Column ss:Index="5" ss:AutoFitWidth="0" ss:Width="220"/>
       <Row ss:Index="6">
        <Cell ss:Index="3" ss:StyleID="s62"/>
       </Row>
       <Row>
        <Cell ss:Index="3" ss:StyleID="s62"/>
       </Row>
       <Row>
        <Cell ss:Index="3" ss:StyleID="s62"/>
       </Row>
       <Row>
        <Cell ss:Index="2"><Data ss:Type="String">57</Data></Cell>    // -- where the id is to be found
        <Cell ss:StyleID="s62"><Data ss:Type="String">Yellow</Data></Cell>
        <Cell><Data ss:Type="String">New</Data></Cell>
       </Row>
       <Row>
        <Cell ss:Index="2"><Data ss:Type="Number">8</Data></Cell>    // -- where the id is to be found
        <Cell ss:StyleID="s62"><Data ss:Type="Number">Black</Data></Cell>
        <Cell><Data ss:Type="Number">Used</Data></Cell>
       </Row>
       <Row>
        <Cell ss:Index="2"><Data ss:Type="Number">25</Data></Cell>    // -- where the id is to be found
        <Cell ss:StyleID="s62"><Data ss:Type="Number">Blue</Data></Cell>
        <Cell><Data ss:Type="Number">Used</Data></Cell>
       </Row>
</Table>

производит требуемый и правильный вывод слияния:

<cars>
   <car id="8">
      <brand>Saab</brand>
      <model>95</model>
      <year>2011</year>
      <color>Black</color>
      <condition>Used</condition>
   </car>
   <car id="57">
      <brand>Chrysler</brand>
      <model>Voyager</model>
      <year>2010</year>
      <color>Yellow</color>
      <condition>New</condition>
   </car>
</cars>

Пояснение:

Правильное использование:

  1. document() функция.

  2. Ключи

  3. <xsl:for-each> Инструкция по изменению текущего документа. В XSLT 1.0 key() Функция работает с текущим документом.

Другие вопросы по тегам