For loops与apply-templates

Luc*_*uke 16 xml xslt xslt-1.0

我最近开始在我的一些XML文档中使用XSLT,我有一些问题.我在下面添加代码.在代码中,我有一个匹配电子书元素的模板.然后我想列出写这本书的所有作者.我使用for为每个循环执行它,但我也可以应用模板.我什么时候使用循环以及何时使用模板时看不清楚.

另一个问题是,当你现在不会在你正在编写它的元素的其他子元素时,只说say-templates是正常的.在我的情况下,在模板中匹配文档根我说的是apply-templates.然后它找到了电子书,它是唯一的孩子,但我可以有一个"书籍"元素区分"常规"书籍和电子书籍然后它只列出书籍的字符数据.如果我只想在我的最终文档中使用电子书,那么我就需要编写apply-templates select ="ebooks".这是一个案例,它取决于你对文件的了解程度如何?

谢谢,这是我的代码(这只是为了练习):

XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="ebooks.xsl"?>
<ebooks>
    <ebook>
        <title>Advanced Rails Recipes: 84 New Ways to Build Stunning Rails Apps</title>
        <authors>
            <author><name>Mike Clark</name></author>
        </authors>
        <pages>464</pages>
        <isbn>978-0-9787-3922-5</isbn>
        <programming_language>Ruby</programming_language>
        <date>
            <year>2008</year>
            <month>5</month>
            <day>1</day>
        </date>
        <publisher>The Pragmatic Programmers</publisher>
    </ebook>
    ...
Run Code Online (Sandbox Code Playgroud)

XSLT:

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

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

    <xsl:template match="ebooks">
        <h1>Ebooks</h1>
        <xsl:apply-templates>
            <xsl:sort select="title"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="ebook">
        <h3><xsl:value-of select="title"/></h3>
        <xsl:apply-templates select="date" />

        <xsl:for-each select="authors/author/name">
            <b><xsl:value-of select="."/>,</b>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="date">
        <table border="1">
            <tr>
                <th>Day</th>
                <th>Month</th>
                <th>Year</th>
            </tr>
            <tr>
                <td><xsl:value-of select="day"/></td>
                <td><xsl:value-of select="month"/></td>
                <td><xsl:value-of select="year"/></td>
            </tr>
        </table>
    </xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

Tom*_*lak 11

这个问题有点争论,但这是我的看法.

我什么时候使用循环以及何时使用模板时看不清楚.

我会说你应该尽可能地避免for-each支持apply-templates.

使用for-each通过添加嵌套级别使您的程序更复杂,并且还可以重新使用for-each块内的代码.使用apply-templateswill(当完成时)生成更灵活和模块化的XSLT.

另一方面:如果你编写一个复杂程度有限的样式表,并且重用性或模块化不是一个问题,使用for-each可能更快更容易(对于人类读者/维护者).所以这部分是个人偏好的问题.

在你的情况下,我会发现这优雅:

<xsl:template match="ebook">
  <!-- ... -->
  <xsl:apply-templates select="authors/author" />
  <!-- ... -->
</xsl:template>

<xsl:template match="authors/author">
  <b>
    <xsl:value-of select="name"/>
    <xsl:if test="position() &lt; last()">,</xsl:if>
  </b>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

对你的另一个问题

另一个问题是,apply-templates当你知道你正在编写它的元素中没有其他孩子时,这是正常的.

当你知道这个元素中永远不会有任何孩子时,写作apply-templates毫无意义.

正确完成后,XSLT能够灵活地处理不同的输入.如果你期望在某些时候可能有孩子,那就apply-templates不会受伤.

一个简单的apply-templates没有select是相当非特异性的,无论是在条件其中(即:所有的人),并以何种顺序(即:输入文档顺序)节点将被处理.因此,您最终可能会处理您从未想要处理的节点或您之前已经处理过的节点.

由于无法为未知节点编写合理的模板,因此我倾向于避免使用非特定 模板,apply-templates并在输入更改时调整我的样式表.

  • 我不确定这一点:"所以这个模板处理很容易并行化.对于每个循环而言,它们都是顺序的." 关于for-each没有任何顺序,目前,Saxon-EE能够在for-each循环上执行并行执行,但不能在apply-templates上执行. (3认同)

Mic*_*Kay 7

总的来说,我同意 Dimitre 的回答。建议初学者使用 xsl:apply-templates 而不是 xsl:for-each 的主要原因是,一旦他们熟悉并熟悉 xsl:apply-templates,他们就不会发现在这两种结构之间做出决定很困难,然而,在他们获得这种经验之前,他们将不恰当地使用 xsl:for-each。

xsl:apply-templates 相对于 for-each 的主要优点是代码可以更好地适应不断变化的文档结构和不断变化的处理要求。很难向那些只想一起破解一些代码而不关心三年后世界会是什么样子的人推销这种好处,但这是一个非常真实的好处。


Dim*_*hev 6

我使用for为每个循环执行它,但我也可以应用模板.我什么时候使用循环以及何时使用模板时看不清楚.

<xsl:for-each>如果确切地知道如何<xsl:for-each>处理,使用绝不是有害的.

麻烦的是许多XSLT的新手在命令式编程方面有经验,可以<xsl:for-each>替代他们最喜欢的PL中的"循环",并认为它允许他们执行不可能的操作 - 比如递增计数器或任何其他修改一个已定义的<xsl:variable>.

<xsl:for-each>XSLT 1.0中一个必不可少的用途是更改当前文档 - 这通常是为了能够key()在文档上使用该函数(与当前源XML文档不同),例如有效地访问驻留的查找表.在自己的xml文档中.

另一方面,使用<xsl:template><xsl:apply-templates>更强大和优雅.

以下是两种方法之间最重要的一些差异:

  1. xsl:apply-templates也更加丰富,比更深xsl:for-each,甚至仅仅是因为我们不知道什么代码将选择的节点上应用-在一般情况下,该代码将是节点列表的不同节点不同.

  2. 将要应用的代码可以在编写xsl:apply templates 之后以及不知道原始作者的人员的方式编写.

FXSL库的实现在XSLT高阶函数(HOF)是不可能的,如果XSLT没有足够的<xsl:apply-templates>指令.

另一个问题是,当你(k)现在不会有你正在编写它的元素的其他孩子时,只是说apply-templates是正常的

<xsl:apply-templates/>
Run Code Online (Sandbox Code Playgroud)

是一个简写:

<xsl:apply-templates select="child::node()"/>
Run Code Online (Sandbox Code Playgroud)

即使当前节点还有其他孩子,你也不在乎,你仍然使用短片,<xsl:apply-templates>并有另一个模板:

<xsl:template match="*"/>
Run Code Online (Sandbox Code Playgroud)

此模板忽略("删除")任何元素.您应该使用更具体的模板覆盖它(在XSLT中,通常,更具体的模板具有更高的优先级,并且选择用于处理匹配同一节点的特定于较少的模板):

<xsl:template match="ebook">
  <!-- Necessary processing here -->
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

我通常不使用,<xsl:template match="*"/>但我使用另一个匹配(并忽略)每个文本节点的模板:

 <xsl:template match="text()"/>
Run Code Online (Sandbox Code Playgroud)

这通常与使用相同<xsl:template match="*"/>,因为XSLT处理没有匹配模板的节点的方式.在任何这种情况下,XSLT都使用其内置模板,这可称为"默认处理".

XSLT默认处理以元素为根的子树的结果是输出此元素的所有文本节点后代的并置(按文档顺序).

因此,防止使用任何文本节点的输出<xsl:template match="text()"/>具有与阻止输出通过使用处理元素相同的(null)输出结果<xsl:template match="*"/>.

摘要:

  1. 模板和<xsl:apply-templates>指令是XSLT如何实现和处理多态的.

  2. 根据XSLT处理模型的精神,使用更多通用模板匹配大类节点并对它们进行一些默认处理,然后使用更具体的模板覆盖通用模板,这些模板匹配并仅处理我们感兴趣的节点.

参考:请参阅此完整主题:http://www.stylusstudio.com/xsllist/200411/post60540.html