在 XSLT 中生成新行
Posted
技术标签:
【中文标题】在 XSLT 中生成新行【英文标题】:Producing a new line in XSLT 【发布时间】:2010-10-17 22:01:00 【问题描述】:我想为 XSLT 中的文本输出生成一个换行符。有什么想法吗?
【问题讨论】:
我想,是时候接受答案了:) 【参考方案1】:以下 XSL 代码将生成 newline(换行符)字符:
<xsl:text>
</xsl:text>
对于carriage return,使用:
<xsl:text>
</xsl:text>
【讨论】:
+1:如果您使用任何可能重新格式化您的 XSL 文件并弄乱空格的东西,这比包含换行方法的<xsl:text>
更健壮。【参考方案2】:
我最喜欢的方法是这样的:
<xsl:stylesheet>
<xsl:output method='text'/>
<xsl:variable name='newline'><xsl:text>
</xsl:text></xsl:variable>
<!-- note that the layout there is deliberate -->
...
</xsl:stylesheet>
然后,每当您想输出换行符(可能在 csv 中)时,您都可以输出如下内容:
<xsl:value-of select="concat(elem1,elem2,elem3,$newline)" />
我在从 xml 输入输出 sql 时使用了这种技术。事实上,我倾向于为逗号、引号和换行符创建变量。
【讨论】:
请注意,下面 Florjon 的回答比我的要稳定得多。 可能值得将声明xml:space="preserve"
添加到 xsl:text
元素以提高稳定性,但我同意 @Florjon 的答案可能更安全。
此解决方案的缺点是还包括任何缩进,这可能是不可取的。【参考方案3】:
在 xsl:output 标记上包含属性 Method="text" 并在 XSL 中的文字内容中的适当位置包含换行符。如果您希望保持 XSL 的源代码整洁,请使用实体 &#10;
在您想要换行的地方。
【讨论】:
【参考方案4】:您可以使用:<xsl:text>&#10;</xsl:text>
查看示例
<xsl:variable name="module-info">
<xsl:value-of select="@name" /> = <xsl:value-of select="@rev" />
<xsl:text> </xsl:text>
</xsl:variable>
如果你把它写在文件中,例如
<redirect:write file="temp.prop" append="true">
<xsl:value-of select="$module-info" />
</redirect:write>
这个变量将在文件中生成一个新行:
commons-dbcp_commons-dbcp = 1.2.2
junit_junit = 4.4
org.easymock_easymock = 2.4
【讨论】:
【参考方案5】:恕我直言,不需要比@Florjon 提供的更多信息。也许留下一些小细节来理解为什么它有时对我们不起作用。
首先,<xsl:text/>
中的&#xa
(十六进制)或&#10
(十进制)将始终有效,但您可能看不到它。
-
html 标记中没有换行符。使用简单的
<br/>
就可以了。否则你会看到一个空白。从浏览器查看源代码会告诉你到底发生了什么。但是,在某些情况下,您会期望这种行为,尤其是在消费者不是直接浏览器的情况下。例如,您想创建一个 HTML 页面,并在将其提供给浏览器之前查看其结构,并使用空行和标识很好地格式化。
记住哪些地方需要使用disable-output-escaping
,哪些地方不需要。以下面的示例为例,我必须从另一个 xml 中创建一个 xml,并从样式表中声明它的 DTD。
第一个版本确实转义了字符(默认为 xsl:text)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" encoding="utf-8"/>
<xsl:template match="/">
<xsl:text><!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd">


</xsl:text>
<xsl:copy>
<xsl:apply-templates select="*" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()" mode="copy">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
结果如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd">
<Subscriptions>
<User id="1"/>
</Subscriptions>
好的,它符合我们的预期,转义是为了正确显示我们使用的字符。根节点内的 XML 部分格式由 ident="yes"
处理。 但仔细观察,我们看到换行符&#xa
没有被转义并按原样翻译,执行了双换行!我对此没有任何解释,很高兴知道。任何人?
第二个版本没有对字符进行转义,因此它们产生了它们的意图。所做的更改是:
<xsl:text disable-output-escaping="yes"><!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd">


</xsl:text>
结果如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd">
<Subscriptions>
<User id="1"/>
</Subscriptions>
那就没问题了。 cr 和 lf 都正确渲染。
-
别忘了我们说的是
nl
,而不是crlf
(nl=lf
)。我的第一次尝试是仅使用 cr:&#xd
并且输出 xml 已由 DOM 正确验证。
我正在查看损坏的 xml:
<?xml version="1.0" encoding="utf-8"?>
<Subscriptions>riptions SYSTEM "Subscriptions.dtd">
<User id="1"/>
</Subscriptions>
DOM 解析器忽略了控制字符,但渲染的却没有。在我意识到我没有看到这一点之前,我花了很长时间才意识到自己是多么愚蠢!
为了记录,我确实在正文中使用了一个带有 CRLF 的变量,只是为了 100% 确保它可以在任何地方工作。
【讨论】:
【参考方案6】:你可以试试,
<xsl:text>
</xsl:text>
它会起作用的。
【讨论】:
【参考方案7】:我添加了您在此处看到的 DOCTYPE
指令:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
<!ENTITY nl "
">
]>
<xsl:stylesheet xmlns:x="http://www.w3.org/2005/02/query-test-XQTSCatalog"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
这允许我使用&nl;
而不是&#xa;
在输出中生成换行符。与其他解决方案一样,这通常放置在 <xsl:text>
标记内。
【讨论】:
【参考方案8】:我赞同 Nic Gibson 的方法,这是 永远是我的最爱:
<xsl:variable name='nl'><xsl:text>
</xsl:text></xsl:variable>
但是我一直在使用 Ant 任务
<xsl:variable name='nl'><xsl:text>
</xsl:text></xsl:variable>
【讨论】:
如果您使用变量,最好使用select
而不是xsl:text
。示例:<xsl:variable name="nl" select="'&#xA;'"/>
这样您就不会创建不必要的 RTF(结果树片段)。【参考方案9】:
我发现 <xsl:text>
中的文字换行符和使用 &#xA;
的文字换行符之间存在区别。
虽然文字换行符在我的环境中运行良好(同时使用 Saxon 和默认的 Java XSLT 处理器),但我的代码在 .NET 环境中运行的另一个组执行时失败。
更改为实体 (&#xA;
) 让我的文件生成代码在 Java 和 .NET 上一致运行。
此外,文字换行符很容易被 IDE 重新格式化,并且当文件由“不知情的人”维护时可能会无意中丢失。
【讨论】:
【参考方案10】:根据我的经验,我注意到生成新行 INSIDE <xsl:variable>
子句不起作用。
我试图做类似的事情:
<xsl:variable name="myVar">
<xsl:choose>
<xsl:when test="@myValue != ''">
<xsl:text>My value: </xsl:text>
<xsl:value-of select="@myValue" />
<xsl:text></xsl:text> <!--NEW LINE-->
<xsl:text>My other value: </xsl:text>
<xsl:value-of select="@myOtherValue" />
</xsl:when>
</xsl:choose>
<xsl:variable>
<div>
<xsl:value-of select="$myVar"/>
</div>
我试图在“新行”(空的<xsl:text>
节点)中添加的任何内容都不起作用(包括此页面中的大多数更简单的建议),更不用说 HTML 不会在那里工作,所以最终我不得不将它拆分为 2 个变量,在 <xsl:variable>
范围之外调用它们,并在它们之间放置一个简单的 <br/>
,即:
<xsl:variable name="myVar1">
<xsl:choose>
<xsl:when test="@myValue != ''">
<xsl:text>My value: </xsl:text>
<xsl:value-of select="@myValue" />
</xsl:when>
</xsl:choose>
<xsl:variable>
<xsl:variable name="myVar2">
<xsl:choose>
<xsl:when test="@myValue != ''">
<xsl:text>My other value: </xsl:text>
<xsl:value-of select="@myOtherValue" />
</xsl:when>
</xsl:choose>
<xsl:variable>
<div>
<xsl:value-of select="$myVar1"/>
<br/>
<xsl:value-of select="$myVar2"/>
</div>
是的,我知道,这不是最复杂的解决方案,但它确实有效,只是分享我在 XSL 方面的 frustration 经验;)
【讨论】:
【参考方案11】:我不能只使用<xsl:text>&#xa;</xsl:text>
方法,因为如果我使用 XSLT 格式化 XML 文件,实体将会消失。所以我不得不使用稍微多一点的方法来使用变量
<xsl:variable name="nl" select="' '"/>
<xsl:template match="/">
<xsl:value-of select="$nl" disable-output-escaping="no"/>
<xsl:apply-templates select="*"/>
</xsl:template>
【讨论】:
【参考方案12】:<xsl:text xml:space="preserve">
</xsl:text>
【讨论】:
【参考方案13】:只需添加这个标签:
<br/>
它对我有用;)。
【讨论】:
问题是关于文本输出的。只有当输出呈现为 HTML 时,您的解决方案才有效。以上是关于在 XSLT 中生成新行的主要内容,如果未能解决你的问题,请参考以下文章