在XSLT中生产新线


197

我想为XSLT中的文本输出生成换行符。有任何想法吗?


11
我认为,该接受答案了:)
Florjon

Answers:


239

以下XSL代码将产生换行符换行符):

<xsl:text>&#xa;</xsl:text>

对于回车,请使用:

<xsl:text>&#xd;</xsl:text>

7
+1:<xsl:text>如果使用任何可能会重新格式化XSL文件并弄乱空格的方法,则此方法比包含换行符的方法要更健壮。
伊恩·罗伯茨

49

我最喜欢的方法是:

<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时,我已经使用了这种技术。实际上,我倾向于为逗号,引号和换行符创建变量。


3
请注意,以下Florjon的答案比我的答案稳定得多。
Nic Gibson

1
可能值得xml:space="preserve"xsl:text元素中添加声明以提高稳定性,但是我同意@Florjon的答案可能更安全。
Flynn1179 2014年

该解决方案的缺点是还包括可能不希望的任何压痕。
wmassingham

47

在xsl:output标记上包括属性Method =“ text”,并在适当的位置在XSL的文字内容中包括换行符。如果您希望保持XSL的源代码整洁&#10;,请在需要换行的位置使用实体。


31

您可以使用: <xsl:text>&#10;</xsl:text>

看例子

<xsl:variable name="module-info">
  <xsl:value-of select="@name" /> = <xsl:value-of select="@rev" />
  <xsl:text>&#10;</xsl:text>
</xsl:variable>

如果您将其写入文件中,例如

<redirect:write file="temp.prop" append="true">
  <xsl:value-of select="$module-info" />
</redirect:write>

此变量将产生一个新行infile,如下所示:

commons-dbcp_commons-dbcp = 1.2.2
junit_junit = 4.4
org.easymock_easymock = 2.4

6

恕我直言,不需要@Florjon提供的更多信息。也许留下一些小细节,以了解为什么有时它对我们不起作用。

首先,a中的&#xa(十六进制)或&#10(十进制)<xsl:text/>将始终有效,但您可能看不到它。

  1. HTML标记中没有换行符。使用简单<br/>会很好。否则,您会看到空白。从浏览器查看源将告诉您真正发生了什么。但是,在某些情况下,您会期望这种行为,尤其是在使用者不是直接浏览器的情况下。例如,您想要创建一个HTML页面,并在将其提供给浏览器之前,以空行和标识很好地查看其结构格式。
  2. 记住要在哪里使用disable-output-escaping和不需要。以以下示例为例,在该示例中,我必须从另一个创建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>&lt;!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd"&gt;&#xa;&#xa;&#xd;</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"?>
&lt;!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd"&gt;

&#13;<Subscriptions>
    <User id="1"/>   
</Subscriptions>

好的,它完成了我们期望的操作,转义完成了,因此我们使用的字符可以正确显示。根节点内部的XML部分格式由处理ident="yes"但是仔细观察一下,我们发现换行符&#xa没有被转义并按原样翻译,执行了两次换行!我对此没有任何解释,很高兴知道。任何人?

第二个版本不会转义字符,因此它们正在产生它们的含义。所做的更改是:

<xsl:text disable-output-escaping="yes">&lt;!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd"&gt;&#xa;&#xa;&#xd;</xsl:text>

结果如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd">

<Subscriptions>
    <User id="1"/>   
</Subscriptions>

没关系。cr和lf都正确渲染。

  1. 别忘了我们在谈论的nl不是crlfnl=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%确保它将在任何地方都有效。


4

我添加了DOCTYPE您在此处看到的指令:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
  <!ENTITY nl "&#xa;">
]>
<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>标签内。



2

我第二次使用Nic Gibson的方法,这始终是我的最爱:

<xsl:variable name='nl'><xsl:text>
</xsl:text></xsl:variable>

但是,我一直在使用Ant任务<echoxml>创建样式表并针对文件运行它们。该任务将执行属性值模板,例如$ {DSTAMP},但也会重新格式化您的xml,因此在某些情况下,最好使用实体引用。

<xsl:variable name='nl'><xsl:text>&#xa;</xsl:text></xsl:variable>

3
如果您使用变量,最好使用select代替xsl:text。示例:<xsl:variable name="nl" select="'&#xA;'"/>这样就不会创建不必要的RTF(结果树片段)。
丹尼尔·哈利

2

我发现使用的文字换行<xsl:text>和使用的文字换行之间的区别&#xA;

尽管文字换行符在我的环境中正常工作(同时使用Saxon和默认的Java XSLT处理器),但是当代码由.NET环境中运行的另一个组执行时,我的代码失败。

更改为实体(&#xA;)后,我的文件生成代码在Java和.NET上始终运行。

同样,原义换行符很容易被IDE重新格式化,并且当文件由“不知道的人”维护时会无意间丢失。


2

我从我的经验,产生一个新行注意到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 分享我的挫败感;)


2

我不能只使用这种<xsl:text>&#xa;</xsl:text>方法,因为如果我使用XSLT格式化XML文件,则该实体将消失。所以我不得不对使用变量的方法进行更全面的了解

<xsl:variable name="nl" select="'&#10;'"/>
<xsl:template match="/">
    <xsl:value-of select="$nl" disable-output-escaping="no"/>
    <xsl:apply-templates select="*"/>
</xsl:template>

-4

只需添加此标签:

<br/>

这个对我有用 ;) 。


7
问题是关于文本输出。仅当输出呈现为HTML时,您的解决方案才有效。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.