在 XSLT 中生成新行

Posted

技术标签:

【中文标题】在 XSLT 中生成新行【英文标题】:Producing a new line in XSLT 【发布时间】:2010-10-17 22:01:00 【问题描述】:

我想为 XSLT 中的文本输出生成一个换行符。有什么想法吗?

【问题讨论】:

我想,是时候接受答案了:) 【参考方案1】:

以下 XSL 代码将生成 newline(换行符)字符:

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

对于carriage return,使用:

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

【讨论】:

+1:如果您使用任何可能重新格式化您的 XSL 文件并弄乱空格的东西,这比包含换行方法的 &lt;xsl:text&gt; 更健壮。【参考方案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 的源代码整洁,请使用实体 &amp;#10; 在您想要换行的地方。

【讨论】:

【参考方案4】:

您可以使用:&lt;xsl:text&gt;&amp;#10;&lt;/xsl:text&gt;

查看示例

<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>

这个变量将在文件中生成一个新行:

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

【讨论】:

【参考方案5】:

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

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

    html 标记中没有换行符。使用简单的&lt;br/&gt; 就可以了。否则你会看到一个空白。从浏览器查看源代码会告诉你到底发生了什么。但是,在某些情况下,您会期望这种行为,尤其是在消费者不是直接浏览器的情况下。例如,您想创建一个 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>&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" 处理。 但仔细观察,我们看到换行符&amp;#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 都正确渲染。

    别忘了我们说的是nl,而不是crlf (nl=lf)。我的第一次尝试是仅使用 cr:&amp;#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>&#xA;</xsl:text>

它会起作用的。

【讨论】:

【参考方案7】:

我添加了您在此处看到的 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">

这允许我使用&amp;nl; 而不是&amp;#xa; 在输出中生成换行符。与其他解决方案一样,这通常放置在 &lt;xsl:text&gt; 标记内。

【讨论】:

【参考方案8】:

我赞同 Nic Gibson 的方法,这是 永远是我的最爱:

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

但是我一直在使用 Ant 任务 创建样式表并针对文件运行它们。这 任务将执行属性值模板,例如$DSTAMP , 但也会重新格式化您的 xml,所以在某些 在这种情况下,实体引用更可取。

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

【讨论】:

如果您使用变量,最好使用select 而不是xsl:text。示例:&lt;xsl:variable name="nl" select="'&amp;#xA;'"/&gt; 这样您就不会创建不必要的 RTF(结果树片段)。【参考方案9】:

我发现 &lt;xsl:text&gt; 中的文字换行符和使用 &amp;#xA; 的文字换行符之间存在区别。

虽然文字换行符在我的环境中运行良好(同时使用 Saxon 和默认的 Java XSLT 处理器),但我的代码在 .NET 环境中运行的另一个组执行时失败。

更改为实体 (&amp;#xA;) 让我的文件生成代码在 Java 和 .NET 上一致运行。

此外,文字换行符很容易被 IDE 重新格式化,并且当文件由“不知情的人”维护时可能会无意中丢失。

【讨论】:

【参考方案10】:

根据我的经验,我注意到生成新行 INSIDE &lt;xsl:variable&gt; 子句不起作用。 我试图做类似的事情:

<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>

我试图在“新行”(空的&lt;xsl:text&gt; 节点)中添加的任何内容都不起作用(包括此页面中的大多数更简单的建议),更不用说 HTML 不会在那里工作,所以最终我不得不将它拆分为 2 个变量,在 &lt;xsl:variable&gt; 范围之外调用它们,并在它们之间放置一个简单的 &lt;br/&gt;,即:

<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】:

我不能只使用&lt;xsl:text&gt;&amp;#xa;&lt;/xsl:text&gt; 方法,因为如果我使用 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>

【讨论】:

【参考方案12】:
<xsl:text xml:space="preserve">
</xsl:text>

【讨论】:

【参考方案13】:

只需添加这个标签:

<br/>

它对我有用;)。

【讨论】:

问题是关于文本输出的。只有当输出呈现为 HTML 时,您的解决方案才有效。

以上是关于在 XSLT 中生成新行的主要内容,如果未能解决你的问题,请参考以下文章

单选按钮不会在 Datagrid 新行中生成对象

xml 在XSLT中生成1-10之间的随机数

xml 在XSLT中生成1-10之间的随机数

在php中生成连续数字[关闭]

如何检测“shift+enter”并在 Textarea 中生成新行?

在数据库中添加新行时,报表工作室中生成的自动更新报表