使用 xslt 从 Excel 的 xml 文件中的 CRLF 输入创建 LF 输出时出现问题

问题描述 投票:0回答:2

我有一些 XML,我想将其转换为 Excel 将在表中打开的 XML。
但是,我的一些源数据使用字符串


来表示 CRLF 并创建一个新行。
据我所知,Excel 仅响应字符串


(仅是 LF),以在单元格内创建新行。
我已经编辑了结果文件以插入字符串


,并且在 Excel 中获得了所需的效果,所以我知道可以做到这一点。

我认为使用像translate 这样的函数将字符串[CRLF] 交换为[LF] 会很简单。但是,到目前为止我还没有成功。

我仅限于 XLST 1.0

使用一些从 W3 借用的简单示例 .xml:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
    <cd>
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
        <comment>Text on one line</comment>
    </cd>
    <cd>
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd>
        <title>Greatest Hits</title>
        <artist>Dolly Parton</artist>
        <country>USA</country>
        <company>RCA</company>
        <price>9.90</price>
        <year>1982</year>
    </cd>
    <cd>
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
        <comment>Text with a break&#13; here (crlf)</comment>
    </cd>

我们可以看到在

<comment>
中使用了字符串
&#13;

在 .xsl 本身中,我使用了这个:

<xsl:for-each select="catalog/cd">
    <!-- TABLE CONTENTS -->
    <Row>
        <!-- Title -->
        <Cell>
            <Data ss:Type="String">
                <xsl:value-of select="title"/>
            </Data>
        </Cell>
        <!-- Artist -->
        <Cell>
            <Data ss:Type="String">
                <xsl:value-of select="artist"/>
            </Data>
        </Cell>
        ...
        <!-- Comment -->
        <Cell>
            <Data ss:Type="String">
                <xsl:value-of disable-output-escaping="yes" select="translate(comment,'&#13;','&#10;')"/>
            </Data>
        </Cell>
    </Row>
</xsl:for-each>

我的 XSL 标题如下所示:

?xml version="1.0" encoding = "UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">

目前效果是这样的:

编辑 Excel 中的设置:

使用 [CRLF] 符号而不是字符串

&#10;
,后者可以在 Excel 中使用并显示内部带有中断的单元格。如果我编辑结果以插入文本字符串
&#10;
Excel 将以所需的方式打破单元格内的文本:

我被 XSLT 1.0 困住了,我是否错过了一些简单的东西?

提前非常感谢。

编辑 操作系统是WIN,我在Notepad++中使用XML工具插件在测试时执行转换。

我只是使用一些网页来测试另一个引擎: 我可以看到字段内有一个中断,但它不是测试字符串

&#10;
,我不相信 Excel 会使用它在单元格内开始新行

excel xml utf-8 xslt-1.0 special-characters
2个回答
0
投票

这(还不是?)答案,但我需要一些代码的空间。

请运行以下测试:

XML

<rows>
    <row>
        <name>no line breaks</name>
        <text>one line only</text>
    </row>
    <row>
        <name>line feed</name>
        <text>first line&#10;second line</text>
    </row>
    <row>
        <name>carriage return</name>
        <text>first line&#13;second line</text>
    </row>
    <row>
        <name>CRLF</name>
        <text>first line&#13;&#10;second line</text>
    </row>
</rows>

XSLT 1.0

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

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="text">
    <xsl:copy>
        <xsl:value-of select="translate(., '&#13;', '&#10;')"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

您应该看到如下所示的结果:

<?xml version="1.0" encoding="UTF-8"?>
<rows>
    <row>
        <name>no line breaks</name>
        <text>one line only</text>
    </row>
    <row>
        <name>line feed</name>
        <text>first line
second line</text>
    </row>
    <row>
        <name>carriage return</name>
        <text>first line
second line</text>
    </row>
    <row>
        <name>CRLF</name>
        <text>first line

second line</text>
    </row>
</rows>

如果您能够查看结果文件的十六进制转储,您应该在中间两行的换行符处看到此序列:

65 0A 73

代表人物

e, LF, s
。最后一行应该是:

65 0A 0A 73

0
投票

XML 解析器将始终规范行结尾,以便输入中的实际 CRLF 序列相当于 NL(又名 LF)字符。但如果换行符被写为实体引用,例如

&#13;
,则不会发生这种情况。

(请注意,

&#13;
是CR,而不是您似乎建议的CRLF。)

如果换行符以这种方式绕过规范化,XSLT 处理器会将它们视为普通字符,就像任何其他字符一样。序列化程序(将 XSLT 结果树转换回词法 XML)会将 CR 字符转换为

&#13;
或其他等效字符,以确保重新解析时能够进行往返。但是 NL 角色可以在往返中幸存,因此不需要这种特殊处理。

您可以使用

translate(., '&#13;', '&#10;')
将 CR 字符转换为 LF。

在 XSLT 1.0 中将 CRLF 转换为 LF 有点困难。如果您知道只有 CRLF 序列,而没有 CR 本身,那么您可以使用

translate(., '&#13;', '')

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.