XSLT:按变量值选择元素

时间:2014-12-02 12:26:21

标签: php xml xslt xpath

我有一些XML结构如下:

<report>
  <columns>
    <column col_id="col_1">Column 1 title</column>
    <column col_id="col_2">Column 2 title</column>
    <column col_id="col_3">Column 3 title</column>
  </columns>
  <rows>
    <row>
      <col_1>Value 1</col_1>
      <!-- No col_2 value exists -->
      <col_3>value 3</col_3>
    </row>
    <row>
      <col_1>Value 1</col_1>
      <col_2>Value 2</col_2>
      <col_3>value 3</col_3>
      <col_4>Value 4</col_4><!-- Not interested in this value -->
    </row>
  </rows>
</report>

我想使用XSLT将此数据输出为HTML表格。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html" encoding="utf-8" indent="yes" />
   <xsl:template match="Report">
      <!-- Get the column names -->
      <xsl:variable name="arr_columns" select="./columns/*" />

      <div id="example_report" class="report">
         <table style="width:100%">
            <thead>
               <tr class="header">
                  <!-- Columns first -->
                  <xsl:for-each select="$arr_columns">
                     <th><xsl:value-of select="." /></th>
                  </xsl:for-each>
               </tr>
            </thead>
            <tbody>
               <!-- Now the actual data -->
               <xsl:for-each select="./rows/row">
                  <xsl:variable name="row" select="." />
                  <tr>
                     <xsl:for-each select="$arr_columns">
                        <xsl:variable name="col_id" select="./@column_id" />
                        <td><xsl:value-of select="$row/$col_id" /></td>
                     </xsl:for-each>
                  </tr>
               </xsl:for-each>
            </tbody>
         </table>
      </div>
   </xsl:template>
</xsl:stylesheet>

我希望<xsl:value-of select="$row/$col_id" />允许我根据存储在col_id变量中的名称选择列。但是,PHP的XSLTProcessor反而爆炸了,报告无法呈现。

  

PHP警告:XSLTProcessor :: transformToXml():没有与此对象关联的样式表

我尝试仅输出$ row(按预期输出整行作为字符串)和$ row / col_1(按预期输出col_1的内容),但尝试访问基于的节点变量的值似乎不起作用。如果我输出$ col_id的值,它会显示我想要输出的节点的名称,以便在循环中正确设置变量。

我猜这是可能的,我做错了,但我很难找到如何正确执行此操作的示例。我确实找到了允许您根据属性选择节点的示例,但正如您可以看到我没有属性的节点,它们的名称表示它们持有的内容。

有人可以帮助为这种情况编写正确的选择器吗?

为了完整性,这是我希望产生的输出:

<table>
  <thead>
    <tr>
      <th>Column 1 title</th>
      <th>Column 2 title</th>
      <th>Column 3 title</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Value 1</td>
      <td></td>
      <td>value 3</td>
    </tr>
    <tr>
      <td>Value 1</td>
      <td>value 2</td>
      <td>value 3</td>
    </tr>
  </tbody>
</table>

2 个答案:

答案 0 :(得分:2)

以这种方式试试吗?

XSLT 1.0

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

<xsl:template match="/report">
    <xsl:variable name="columns" select="columns/column" />
    <table style="width:100%">
        <thead>
            <tr>
                <xsl:for-each select="$columns">
                     <th><xsl:value-of select="." /></th>
                </xsl:for-each>
            </tr>
        </thead>
        <tbody>
            <xsl:for-each select="rows/row">
                <xsl:variable name="current-row" select="." />
                <tr>
                     <xsl:for-each select="$columns">
                        <td><xsl:value-of select="$current-row/*[local-name()=current()/@col_id]"/></td>
                     </xsl:for-each>
                </tr>
            </xsl:for-each>
        </tbody>
    </table>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

特别是因为您在输入XML中的元素与目标HTML中的元素之间有这样清晰的映射,所以请考虑更加面向匹配的声明性方法,而不是当前基于程序的基于循环的方法:

陈述性方法

[根据@ michael.hor257k的观察结果更新了匹配row后的一些程序循环有助于满足省略的col_单元格必须导致空{{}的要求1}}当关联的td存在时。]

column