【问题标题】:template mode loop behavior模板模式循环行为
【发布时间】:2018-02-20 09:47:01
【问题描述】:

我想通过 xslt 转换从 xml 生成一个简单的树结构。

xml 源代码如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="style.xslt"?>
<root>
    <pi>
        <id>P1</id>
        <s>
            <sc>
                <id>SC1</id>
                <si>
                    <id>SI1</id>
                </si>
                <sc>
                    <id>SC2</id>
                    <si>
                        <id>SI2</id>
                    </si>
                    <si>
                        <id>SI3</id>
                    </si>
                </sc>
            </sc>
            <sc>
                <id>SC3</id>
                <si>
                    <id>SI4</id>
                </si>
            </sc>
            <si>
                <id>SI6</id>
            </si>
        </s>
    </pi>
</root>

这是我的 xslt 代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" indent="yes"/>
    <xsl:template match="xsl:stylesheet"/>
    <xsl:template match="/">
        <html>
            <head>
                <meta charset="utf-8"/>
                <title> Test </title>
            </head>
            <body>
                <h1> Test </h1>
                <xsl:for-each select=".">
                    <xsl:call-template name="PH"/>
                    <div>
                        <xsl:call-template name="Structure"/>
                    </div>
                </xsl:for-each>
            </body>
        </html>
    </xsl:template>
    <!-- Header -->
    <xsl:template name="PH" match="//pi">
        <div>
            <h2> PI </h2>
            <table>
                <tr>
                    <td>Identifier:</td>
                    <td>
                        <xsl:value-of select="//pi/id"/>
                    </td>
                </tr>
            </table>
        </div>
    </xsl:template>
    <!-- Structure -->
    <xsl:template name="Structure" match="//s">
        <div>Structure</div>
        <xsl:apply-templates select="//s/sc"/>
        <xsl:apply-templates select="//s/si"/>
    </xsl:template>
    <!-- Container -->
    <xsl:template match="//s/sc" mode="loop">
        <div><xsl:value-of select="id"/></div>
    </xsl:template>
    <xsl:template match="//sc/sc" mode="loop">
        <div><xsl:value-of select="id"/></div>
    </xsl:template>
    <!-- Item -->
    <xsl:template name="StructueItem" match="//s/si">
        <div><xsl:value-of select="id"/></div>
    </xsl:template>
    <xsl:template name="StructueItem1" match="//sc/si">
        <div><xsl:value-of select="id"/></div>
    </xsl:template>
</xsl:stylesheet>

我希望在生成的 HTML 中包含来自 xml 源的所有 HTML 标记和内容。但是转换结果中所有sc xml元素都没有周围的div标签。

<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <meta charset="utf-8">
      <title> Test </title>
   </head>
   <body>
      <h1> Test </h1>
      <div>
         <h2> PI </h2>
         <table>
            <tr>
               <td>Identifier:</td>
               <td>P1</td>
            </tr>
         </table>
      </div>
      <div>
         <div>Structure</div>
         SC1      
         <div>SI1</div>
         SC2
         <div>SI2</div>
         <div>SI3</div>
         SC3
         <div>SI4</div>
         <div>SI6</div>
      </div>
   </body>
</html>

我在哪里做错了?

谢谢!

【问题讨论】:

  • 您能否编辑您的问题以显示预期的输出应该是什么?谢谢!
  • 请注意,您犯的一个“错误”是您有两个模板匹配,其中 mode 设置为“循环”,但您在任何使用此模式的地方都没有任何 xsl:apply-templates,所以这些模板永远不会匹配。
  • 结果应该是这样的:
    Structure
    SC1
    SI1
    SC2
    SI2
    SI3
    SC3
    SI4
    SI6

标签: html xml xslt transformation


【解决方案1】:

关于您的源 XML 的第一条评论: 正如你所期望的那样,&lt;div&gt;SI6&lt;/div&gt;SC3 之下,我认为

<si>
  <id>SI6</id>
</si>

应该“上移” - 在上面的 &lt;sc&gt; 元素内。

我对你的脚本做了一些改动。

  1. 我没有调用Structure模板,而是移动了它的内容 (有一点例外)到呼叫地点。

  2. 当您“按名称”(而不是“按匹配”)调用某些模板时, 我从它们中删除了match 属性,以使脚本更清晰。

  3. 由于根节点只有一个,所以主模板中的for-each循环 (匹配“/”)是不需要的。

  4. 基本思想是我从主模板应用模板 到所有后代sc 元素。

  5. 匹配sc的模板,反过来,首先打印自己的id元素 然后将模板应用到其子 si 元素。

所以整个脚本如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>

  <xsl:template match="/">
    <html>
      <head>
        <meta charset="utf-8"/><title> Test </title>
      </head>
      <body>
        <h1> Test </h1>
        <xsl:call-template name="PH"/>
        <div>
          <div>Structure</div>
          <xsl:apply-templates select="//sc"/>
        </div>
      </body>
    </html>
  </xsl:template>

  <!-- Header -->
  <xsl:template name="PH">
    <div>
      <h2> PI </h2>
      <table>
        <tr>
          <td>Identifier:</td>
          <td><xsl:value-of select="//pi/id"/></td>
        </tr>
      </table>
    </div>
  </xsl:template>

  <xsl:template match="sc">
    <xsl:value-of select="id"/>
    <xsl:apply-templates select="si"/>
  </xsl:template>

  <xsl:template match="si">
    <div>
      <xsl:value-of select="id"/>
    </div>  
  </xsl:template>
</xsl:stylesheet>

有关工作示例,请参阅http://xsltransform.net/3MEbY6F 它适用于 XalanSaxon 引擎。

【讨论】:

    猜你喜欢
    • 2013-09-12
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 2012-07-25
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多