【问题标题】:XSL XML LoopingXSL XML 循环
【发布时间】:2011-12-06 19:31:42
【问题描述】:

我有一个 XML 文件,我正在使用 XSL 将其转换为 html 页面。我想遍历包含许多父节点的 XML 文件,然后遍历子节点并将结果显示在 HTML 表中。

到目前为止,我能够遍历父节点并成功返回它们,但是当我在其中嵌套一个 for-each 循环以返回子节点的属性时,我最终会返回文档中所有子节点的属性,而不是特定于父节点的属性。

任何人都可以对此有所了解。

XML:

<AdminReports xmlns="30/11/2011 09:25:58">
    <AdminReport ID="1">
        <DataSourceInformation DataSourceID="12" Value="DSI_50"/>
    </AdminReport>
    <AdminReport ID="2">
        <DataSourceInformation DataSourceID="23" Value="DSI_30"/>
    </AdminReport>
    <AdminReport ID="3">
        <DataSourceInformation DataSourceID="34" Value="DSI_20"/>
    </AdminReport>
</AdminReports>

XSL:

  <table border="1" cellspacing="2" width="800" bgcolor="white">
 <xsl:for-each select="/*/*[name()='AdminReport']">
       <tr bgcolor="9acd32">
       <table><th>Admin Report Num:</th></table>
       <table><th><xsl:value-ofselect="@ID"/>   </th></table>
    </tr>
    <tr>    
     <xsl:for-each select="/*/*/*[name()='DataSourceInformation']"> 
      <table><th>Data Report ID:</th></table>
              <table><th><xsl:value-of select="@DataSourceID"/></th></table>
     </xsl:for-each>
     </tr>
    </xsl:for-each>
</table>

【问题讨论】:

  • 为什么&lt;table&gt;&lt;th&gt; **** &lt;/th&gt;&lt;/table&gt;被写了这么多次?
  • 这是一个奇怪的命名空间。命名空间的 XML 规则非常模糊。一些工具/解析器可能会让你侥幸逃脱,但迟早你会找到一个不会的。

标签: xml xslt


【解决方案1】:

这可以使用模板而不是for-each 更简洁地完成:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                              xmlns:x="30/11/2011 09:25:58">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:template match="/">
        <table border="1" cellspacing="2" width="800" bgcolor="white">
            <xsl:apply-templates/>
        </table>
    </xsl:template>
    <xsl:template match="x:AdminReport">
        <tr bgcolor="9acd32">
            <table><th>Admin Report Num:</th></table>
            <table><th><xsl:value-of select="@ID"/></th></table>
        </tr>
        <tr><xsl:apply-templates/></tr>
    </xsl:template>
    <xsl:template match="x:DataSourceInformation">
        <table><th>Data Report ID:</th></table>
        <table><th><xsl:value-of select="@DataSourceID"/></th></table>
    </xsl:template>
</xsl:stylesheet>

注意事项

  • 每个部分都有自己的模板,可以更清晰地构建样式表
  • 将来使用这种方法处理新元素会更容易
  • 我将您的命名空间注册到前缀x,这样我就可以引用x:DataSourceInformation 之类的元素,而不是*[name()='DataSourceInformation']
  • for-each 在 XSLT 中很少需要;模板几乎总是更自然的解决方案
  • 如果你坚持for-each,那就看@GSerg的回答

【讨论】:

  • 很好的总结@lwburk。我们都走在同一条路上。
【解决方案2】:

你过于复杂了。

select 相对于当前上下文节点:

<table border="1" cellspacing="2" width="800" bgcolor="white">
    <xsl:for-each select="/*/*[name()='AdminReport']">
       <tr bgcolor="9acd32">
       <table><th>Admin Report Num:</th></table>
       <table><th><xsl:value-of select="@ID"/>   </th></table>
       </tr>
       <tr> 
       <xsl:for-each select="*[name()='DataSourceInformation']">    
           <table><th>Data Report ID:</th></table>
           <table><th><xsl:value-of select="@DataSourceID"/></th></table>
       </xsl:for-each>
       </tr>
     </xsl:for-each>
</table>

【讨论】:

  • 谢谢。这正是我所需要的。
  • 当然,/*/*[name()='AdminReport'] 可以而且应该简化为 /*/n:AdminReport,其中前缀 n 绑定到相关的命名空间。
  • @MichaelKay 是的。但据我了解,该文档有许多AdminReports,每个都有一个独特的xmlnsxmlns 对于日期时间来说是一个有点奇怪的地方)。这证明了 OP 在他的 XSL 中展示的努力是正确的。
【解决方案3】:

更容易将 XSLT 视为声明性模板匹配引擎。查看此示例中的 xsl:template 和 xsl:apply-template 元素。祝你好运!

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ns="30/11/2011 09:25:58">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/ns:AdminReports">
    <table border="1" cellspacing="2" width="800" bgcolor="white">
      <xsl:apply-templates select="ns:AdminReport"/>
    </table>
  </xsl:template>

  <xsl:template match ="ns:AdminReport">
      <tr bgcolor="9acd32">
        <th>Admin Report Num:</th>
        <th>
          <xsl:value-of select="@ID"/>
        </th>
      </tr>
      <tr>
        <xsl:apply-templates select="ns:DataSourceInformation" />
      </tr>
  </xsl:template>

  <xsl:template match="ns:DataSourceInformation" >
      <table>
        <th>Data Report ID:</th>
      </table>
      <table>
        <th>
          <xsl:value-of select="@DataSourceID"/>
        </th>
      </table>
  </xsl:template>

</xsl:stylesheet>

【讨论】:

    【解决方案4】:

    value-ofselect之间没有空格

    <xsl:value-ofselect="@ID"/>
    

    应该是&lt;xsl:value-of select="@ID"/&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-11
      • 1970-01-01
      • 2017-07-13
      • 2018-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多