想象一下,我的XML文件如下所示:
<root>
<test>
Lorem ipsum dolor sit amet, <randomTag>consectetur</randomTag>
adipiscing elit, sed do <randomTag>eiusmod</randomTag> tempor
incididunt ut labore et dolore magna aliqua...
</test>
</root>
以下代码不起作用:
<xsl:template match="/">
<xsl:apply-templates select="substring(test,1,50)"/> ...
</xsl:template>
<xsl:template match="randomTag">
<myTag><xsl:value-of select="."/></myTag>
</xsl:template>
我期待以下输出:
Lorem ipsum dolor sit amet, <myTag>consectetur</myTag>
adipiscing...
如果我用 test 替换 substring(test,1,50),它可以工作,但我只需要前50个字符。
我也尝试过以这种方式使用变量:
<xsl:template match="/">
<xsl:variable name="aux" select="substring(test,1,50)"/>
<xsl:apply-templates select="$aux"/> ...
</xsl:template>
但即便如此。
在我看来,问题是 substring()表达式。 一些建议?
答案 0 :(得分:2)
<xsl:apply-templates>
仅适用于node-set
,即原始文档中的一组节点。
在许多XSLT处理器中,您可以使用exsl:node-set扩展功能创建其他node-set
。
答案 1 :(得分:1)
在XSLT 3.0之前,apply-templates必须选择节点(不是字符串或其他原子值),匹配模式只能匹配节点。 substring()函数提供一个字符串,并丢弃有关元素的任何信息。所以是的,substring()表达式就是问题所在。
那你怎么解决这个问题呢?答案是一种名为&#34;兄弟递归的技术&#34;。您将模板(通常以特定模式)应用于第一个子项,此模板对紧随其后的兄弟模板执行apply-templates。作为apply-templates的参数,您传递一个参数,指示何时停止(例如,最初将其设置为50,并在处理每个节点时减少字符数,当它达到零时,终止递归。)
答案 2 :(得分:0)
正如我在评论中已经提到的,如果要缩短的文本在子树的节点之间分割,那么这会变得复杂。它很复杂,因为 - 从概念上讲,至少 - XSLT并行处理树的分支,并且没有办法将信息从一个分支传递到下一个分支,就像你在进行循环时一样。
您可以采取两种可能的方法:
第二种选择似乎更容易,但效率非常低。这是一个通用的例子:
<强> XML 强>
在本文档中,我插入了§
作为每个项目正文的第100个字符。
<feed>
<item>
<title>Declaration</title>
<body>
<para>When in the Course of human events, it becomes necessary for one people to <bold>dissolve the political b§ands which have connected them with another</bold>, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.</para>
<para>We hold these truths to be self-evident, that all men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the pursuit of Happiness.</para>
</body>
</item>
<item>
<title>Lorem Isum</title>
<body>
<para>Lorem ipsum dolor sit amet consectetuer adipiscing elit. <bold>Nam interdum ante quis <italic>erat pellentesque e§lementum.</italic> Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</bold> Ut molestie quam sit amet ligula.</para>
<para>In enim. Duis dapibus hendrerit quam. Donec hendrerit lectus vel nunc. Vestibulum sit amet pede nec neque dignissim vehicula.</para>
<para>Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Phasellus eget ante. Quisque risus leo, dictum sit amet, nonummy sit amet, consectetuer ut, mi.</para>
</body>
</item>
<item>
<title>Subject</title>
<body>
<para>Subject to change without notice.</para>
<para>Not responsible for direct, indirect, incidental or consequential §damages resulting from any defect, error or failure to perform.</para>
<para>May be too intense for some viewers.</para>
</body>
</item>
</feed>
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="limit" select="100"/>
<xsl:template match="feed">
<body>
<xsl:apply-templates/>
</body>
</xsl:template>
<xsl:template match="item">
<h3><xsl:value-of select="title"/></h3>
<xsl:apply-templates select="body"/>
<hr/>
</xsl:template>
<xsl:template match="body">
<p>
<xsl:apply-templates mode="summary"/>
</p>
</xsl:template>
<xsl:template match="bold" mode="summary">
<b>
<xsl:apply-templates mode="summary"/>
</b>
</xsl:template>
<xsl:template match="italic" mode="summary">
<i>
<xsl:apply-templates mode="summary"/>
</i>
</xsl:template>
<xsl:template match="text()" mode="summary">
<xsl:variable name="text-before">
<xsl:value-of select="ancestor::body//text()[current() >> .]" separator=""/>
</xsl:variable>
<xsl:variable name="used" select="string-length($text-before)" />
<xsl:if test="$used lt $limit">
<xsl:value-of select="substring(., 1, $limit - $used)"/>
<xsl:if test="string-length(.) + $used ge $limit">
<xsl:text>...</xsl:text>
</xsl:if>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
<强>结果强>
<body>
<h3>Declaration</h3>
<p>When in the Course of human events, it becomes necessary for one people to <b>dissolve the political bß...</b>
</p>
<hr/>
<h3>Lorem Isum</h3>
<p>Lorem ipsum dolor sit amet consectetuer adipiscing elit. <b>Nam interdum ante quis <i>erat pellentesque e§...</i>
</b>
</p>
<hr/>
<h3>Subject</h3>
<p>Subject to change without notice.Not responsible for direct, indirect, incidental or consequential ß...</p>
<hr/>
</body>
<强>渲染强>
如您所见,每个项目在完全100个字符后被切断,同时保留内部层次结构,并且可以单独处理每种类型的节点。
注意:强>
在我写完这篇文章之后,我去看了你所链接的other question。接受的答案与此非常相似,但我相信我的更简单和它会分别处理每个项目。