使用XSLT显示数据

时间:2013-02-27 06:21:14

标签: xml xslt

我有

的xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="test1.xsl"?>
<products>
    <node>
        <node>
            <dist_value>
            <node> 55 </node>
            <node> 59 </node>
            <node> 72 </node>
            </dist_value>
            <reg_str_dt>
            <node> 2013-08-03 17:29:00 </node>
            </reg_str_dt>
            <product_id> 1 </product_id>
        </node>
    </node>
    <node>
        <node>
            <dist_value>
            <node> 72 </node>
            <node> 19 </node>
            <node> 49 </node>
            </dist_value>
            <reg_str_dt>
            <node> 2013-10-25 17:29:00 </node>
            </reg_str_dt>
            <product_id> 2 </product_id>
        </node>
    </node> 
    <node>
        <node>
            <dist_value>
            <node> 12 </node>
            <node> 548 </node>
            <node> 112 </node>
            </dist_value>
            <reg_str_dt>
            <node> 2013-08-12 17:29:00 </node>
            </reg_str_dt>
            <name> test </name>
            <product_id> 3 </product_id>
        </node>
    </node>
</products>

我已经写了这个xslt来显示dist_value\node < 50的产品的所有数据,并且它将提供产品2 & 3的输出数据

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

  <xsl:template match="/">
   <html>
    <body>

     <table border="1">
      <tr><th>Product ID</th><th>Product DATA</th></tr>
      <xsl:apply-templates select="products/node/node" />
     </table>
    </body>
   </html>
  </xsl:template>

  <xsl:template match="products/node/node/dist_value[node &lt; 50]">
   <tr>
    <td><xsl:value-of select="//product_id" /></td>
    <td><xsl:value-of select="products/node/node/*" /></td> 
   </tr>
  </xsl:template> 

</xsl:stylesheet>

我是xslt的初学者,这里有些不对劲

我希望输出类似这样的东西

Product ID  |   Product DATA
--------------------------------
2           |dist_value  => 72
            |               19
            |               79
            |reg_str_dt =>  2013-10-25 17:29:00
            |product_id => 2

产品3包含名称

4 个答案:

答案 0 :(得分:1)

您需要稍微修改模板选择语句。 在匹配语句中,您选择<dist_value>个节点,因此在模板的其余部分中,select语句需要相对于<dist_value>节点,如下所示:

<xsl:template match="products/node/node/dist_value[node &lt; 50]">
  <tr>
    <td>
      <xsl:value-of select="../product_id" />
    </td>
    <td>
      <xsl:for-each select="./node">
        <xsl:value-of select="."/>
        <br/>
      </xsl:for-each>
      <xsl:value-of select="../reg_str_dt/node" />
    </td>
  </tr>
</xsl:template>

答案 1 :(得分:1)

了解XSLT的一个方面是它具有内置模板的概念。如果要查找与元素匹配的模板,但在XSLT中不存在一个模板,则将使用这些模板。在您的情况下,您可以通过查找节点元素

来开始
<xsl:apply-templates select="products/node/node" />

但是,您的模板符合 dist_value 元素

<xsl:template match="products/node/node/dist_value[node &lt; 50]">

这意味着XSLT将开始使用内置模板,它将输出元素的文本,然后处理任何子元素。您可能应该这样做以匹配节点元素。

<xsl:template match="products/node/node[dist_value/node &lt; 50]">

虽然您还需要一个模板来匹配 dist_value 不小于50的节点元素。或者您可以更改apply-templates以仅选择那些你想要

<xsl:apply-templates select="products/node/node[dist_value/node &lt; 50]" />

您遇到的另一个问题是 dist_value 模板

中的这一行
<xsl:value-of select="//product_id" />

双斜杠意味着它将寻找相对于根元素的 product_id ,并始终选择第一个。您只需要执行此操作,以查找相对于当前节点元素的product_id

<xsl:value-of select="product_id" />

这是完整的XSLT

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

   <xsl:template match="/">
      <html>
         <body>
            <table border="1">
               <tr>
                  <th>Product ID</th>
                  <th>Product DATA</th>
               </tr>
               <xsl:apply-templates select="products/node/node[dist_value/node &lt; 50]"/>
            </table>
         </body>
      </html>
   </xsl:template>

   <xsl:template match="products/node/node">
      <tr>
         <td>
            <xsl:value-of select="product_id"/>
         </td>
         <td>
            <xsl:apply-templates select="dist_value/node"/>
         </td>
      </tr>
      <tr>
         <td/>
         <td>
            <xsl:value-of select="reg_str_dt/node"/>
         </td>
      </tr>
      <tr>
         <td/>
         <td>
            <xsl:value-of select="product_id"/>
         </td>
      </tr>
   </xsl:template>

   <xsl:template match="dist_value/node">
      <xsl:value-of select="concat(., '&#10;')"/>
   </xsl:template>
</xsl:stylesheet>

应用于XML时,输出以下内容

<html>
   <body>
      <table border="1">
         <tr>
            <th>Product ID</th>
            <th>Product DATA</th>
         </tr>
         <tr>
            <td> 2 </td>
            <td> 72 19 49 </td>
         </tr>
         <tr>
            <td/>
            <td> 2013-10-25 17:29:00 </td>
         </tr>
         <tr>
            <td/>
            <td> 2 </td>
         </tr>
         <tr>
            <td> 3 </td>
            <td> 12 548 112 </td>
         </tr>
         <tr>
            <td/>
            <td> 2013-08-12 17:29:00 </td>
         </tr>
         <tr>
            <td/>
            <td> 3 </td>
         </tr>
      </table>
   </body>
</html>

答案 2 :(得分:1)

你的代码有很多错误。专注于了解上下文节点,应用模板以及处理器如何在节点上进行迭代。你的架构也很尴尬;如果可以,请考虑将“node / node”替换为“product”。

这是一个XSL:

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

<xsl:template match="/">
    <html>
        <body>
            <table border="1">
                <tr><th>Product ID</th><th>Product DATA</th></tr>
                <xsl:apply-templates select="/products/node/node" />
            </table>
        </body>
    </html>
</xsl:template>

<!-- ignore the node with dist_value child by default -->
<xsl:template match="node[ dist_value ]" />
<xsl:template match="node[ dist_value[node &lt; 50] ]" priority="1.0">
    <xsl:variable name="span" select="1 + count( * )" />
    <tr>
        <td align="center" rowspan="{$span}"><xsl:value-of select="product_id" /></td>
    </tr>
    <xsl:apply-templates />
</xsl:template> 

<xsl:template match="name">
    <tr>
        <td>
            <xsl:value-of select="name()" />
            <xsl:text disable-output-escaping="yes"> => </xsl:text>
            <xsl:value-of select="." />
        </td>
    </tr>
</xsl:template>

<xsl:template match="dist_value">
    <tr>
        <td>
            <xsl:value-of select="name()"/>
            <xsl:text disable-output-escaping="yes"> =&gt; </xsl:text>
            <xsl:for-each select="*">
                <xsl:if test="position()>1">
                    <xsl:text>, </xsl:text>
                </xsl:if>
                <xsl:value-of select="normalize-space(.)" />
            </xsl:for-each> 
        </td>
    </tr>
</xsl:template>

<xsl:template match="reg_str_dt">
    <tr>
        <td>
            <xsl:value-of select="name()"/>
            <xsl:text disable-output-escaping="yes"> =&gt; </xsl:text>
            <xsl:value-of select="node" />
        </td>
    </tr>
</xsl:template>

<xsl:template match="product_id">
    <tr>
        <td>
            <xsl:value-of select="name()"/>
            <xsl:text disable-output-escaping="yes"> =&gt; </xsl:text>
            <xsl:value-of select="." />
        </td>
    </tr>
</xsl:template>

这是输出HTML:

<?xml version="1.0" encoding="UTF-8"?>
<html>
   <body>
      <table border="1">
         <tr>
            <th>Product ID</th>
            <th>Product DATA</th>
         </tr>
         <tr>
            <td align="center" rowspan="4">2</td>
         </tr>
         <tr>
            <td>dist_value =&gt; 72, 19, 49</td>
         </tr>
         <tr>
            <td>reg_str_dt =&gt;  2013-10-25 17:29:00</td>
         </tr>
         <tr>
            <td>product_id =&gt;  2</td>
         </tr>
         <tr>
            <td align="center" rowspan="5">3</td>
         </tr>
         <tr>
            <td>dist_value =&gt; 12, 548, 112</td>
         </tr>
         <tr>
            <td>reg_str_dt =&gt;  2013-08-12 17:29:00</td>
         </tr>
         <tr>
            <td>name =&gt;  test</td>
         </tr>
         <tr>
            <td>product_id =&gt;  3</td>
         </tr>
      </table>
   </body>
</html>

答案 3 :(得分:1)

对于/products/node/node中可能出现的不同元素,这是另一个更灵活的选项。 node子项内/products/node/node个元素的数量也更灵活。

XML输入(已修改为显示一些其他测试值以显示)

<products>
    <node>
        <node>
            <dist_value>
                <node> 55 </node>
                <node> 59 </node>
                <node> 72 </node>
            </dist_value>
            <reg_str_dt>
                <node> 2013-08-03 17:29:00 </node>
            </reg_str_dt>
            <product_id> 1 </product_id>
        </node>
    </node>
    <node>
        <node>
            <dist_value>
                <node> 72 </node>
                <node> 19 </node>
                <node> 49 </node>
            </dist_value>
            <reg_str_dt>
                <node> 2013-10-25 17:29:00 </node>
                <node>additional test value 1</node>
                <node>additional test value 2</node>
            </reg_str_dt>
            <product_id> 2 </product_id>
        </node>
    </node> 
    <node>
        <node>
            <dist_value>
                <node> 12 </node>
                <node> 548 </node>
                <node> 112 </node>
            </dist_value>
            <reg_str_dt>
                <node> 2013-08-12 17:29:00 </node>
            </reg_str_dt>
            <name> test </name>
            <product_id> 3 </product_id>
        </node>
    </node>
</products>

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/products" priority="1">
        <html>
            <body>
                <table border="1">
                    <tr>
                        <th>Product ID</th>
                        <th colspan="2">Product DATA</th>
                    </tr>
                    <xsl:apply-templates select="node[node/dist_value/node &lt; 50]"/>
                </table>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="node/node">
        <tr>
            <td>
                <xsl:value-of select="product_id"/>
            </td>
            <td><xsl:value-of select="name(*[1])"/> --></td> 
            <td><xsl:value-of select="*[1]/*[1]"/></td>
        </tr>
        <xsl:apply-templates select="*[not(self::product_id)]"/>
    </xsl:template>

    <!--These 2 templates will handle the data on the same
    row as the Product ID.-->
    <xsl:template match="node/node/*[1]" priority="1">
        <xsl:apply-templates mode="newrow"/>
    </xsl:template>
    <xsl:template match="node/node/*[1]/*[1]" mode="newrow"/>

    <xsl:template match="*" mode="newrow">
        <xsl:call-template name="dataRow"/>
    </xsl:template>

    <xsl:template match="node/node/*/*[not(position()=1)]">
        <xsl:call-template name="dataRow"/>
    </xsl:template>

    <xsl:template name="dataRow">
        <tr>
            <td/>
            <td/>
            <td><xsl:value-of select="."/></td>
        </tr>       
    </xsl:template>

    <xsl:template match="*[not(self::node)]">
        <tr>
            <td/>
            <td><xsl:value-of select="name()"/> --></td>
            <td><xsl:apply-templates/></td>
        </tr>
    </xsl:template>

</xsl:stylesheet>

HTML输出(代码)

<html>
   <body>
      <table border="1">
         <tr>
            <th>Product ID</th>
            <th colspan="2">Product DATA</th>
         </tr>
         <tr>
            <td> 2 </td>
            <td>dist_value --&gt;</td>
            <td> 72 </td>
         </tr>
         <tr>
            <td></td>
            <td></td>
            <td> 19 </td>
         </tr>
         <tr>
            <td></td>
            <td></td>
            <td> 49 </td>
         </tr>
         <tr>
            <td></td>
            <td>reg_str_dt --&gt;</td>
            <td> 2013-10-25 17:29:00 
               <tr>
                  <td></td>
                  <td></td>
                  <td>additional test value 1</td>
               </tr>
               <tr>
                  <td></td>
                  <td></td>
                  <td>additional test value 2</td>
               </tr>
            </td>
         </tr>
         <tr>
            <td> 3 </td>
            <td>dist_value --&gt;</td>
            <td> 12 </td>
         </tr>
         <tr>
            <td></td>
            <td></td>
            <td> 548 </td>
         </tr>
         <tr>
            <td></td>
            <td></td>
            <td> 112 </td>
         </tr>
         <tr>
            <td></td>
            <td>reg_str_dt --&gt;</td>
            <td> 2013-08-12 17:29:00 </td>
         </tr>
         <tr>
            <td></td>
            <td>name --&gt;</td>
            <td> test </td>
         </tr>
      </table>
   </body>
</html>

HTML输出(在IE中显示)

enter image description here