【问题标题】:Preserving attribute whitespace保留属性空白
【发布时间】:2010-09-20 14:23:51
【问题描述】:

免责声明:以下是针对 XML 的犯罪。这就是为什么我试图用 XSLT 来改变它:)

我的 XML 当前如下所示:

<root>
    <object name="blarg" property1="shablarg" property2="werg".../>
    <object name="yetanotherobject" .../>
</root>

是的,我将所有文本数据放入属性中。我希望 XSLT 可以拯救我;我想朝着这样的方向前进:

<root>
    <object>
        <name>blarg</name>
        <property1>shablarg</name>
        ...
    </object>
    <object>
        ...
    </object>
</root>

到目前为止,我实际上已经完成了所有这些工作,除了我对 XML 的罪过更加……特别。一些标签看起来像这样:

<object description = "This is the first line

This is the third line.  That second line full of whitespace is meaningful"/>

我在 linux 下使用 xsltproc,但它似乎没有任何选项来保留空格。我尝试使用 xsl:preserve-space 和 xml:space="preserve" 无济于事。我发现的每个选项似乎都适用于在元素本身内保留空格,但不适用于属性。每次,以上内容都会更改为:

这是第一行 这是第三行。充满空格的第二行是有意义的

所以问题是,我可以保留属性空白吗?

【问题讨论】:

  • 您应该将空格替换为属性值内部的实体引用,例如将&lt;object description="first line \n next line"/&gt; 替换为&lt;object description="first line&amp;#xA;next line"/&gt;。属性值规范化(3.3.3)然后取决于我认为默认为CDATA 的属性类型。但是我认为你可以用&lt;!DOCTYPE root [ &lt;!ATTLIST object description CDATA #IMPLIED&gt;'&gt; 强制它——可能正确也可能不正确。然后,如果你有一个 XSL,你需要确保手动处理你的空白,我的做法与 string-join()tokenize() 类似。
  • 可以做到。你可以从我对另一个问题的回答中得到一个完整的例子(SSCCE):stackoverflow.com/a/29780972/611007 (正如我上面解释的,这不是你尝试做的方式,但最终,它会像你想要的那样工作。)

标签: xml xslt whitespace


【解决方案1】:

这实际上是一个原始的 XML 解析问题,不是 XSLT 可以帮助您解决的问题。根据 XML 标准中的“3.3.3 属性值规范化”,XML 解析必须将该属性值中的换行符转换为空格。因此,当前读取您的描述属性并保留换行符的任何内容都是错误的。

您可以通过预处理 XML 以将换行符转义为 & #10; 来恢复换行符。字符引用,只要您还没有在不允许使用 charrefs 的地方换行,例如在标签正文中。 Charrefs 应该作为控制字符一直存在到属性值,然后您可以将它们转换为文本节点。

【讨论】:

  • 我不确定这是否可行。 Charrefs 被 XML 处理器所代表的字节替换,因此引用空白字符(如 LINE FEED)的 charref 将被规范化为空白。
  • 标准和 DOM 测试套件说它有效;您的实现可能会有所不同,但我测试过的会有所不同。
  • @ChuckB 我认为这取决于您是否可以控制您的 xml 处理器。我可以使用.xsl 创建一个很好的输出,它可以在 saxon 和 firefox 中使用。
  • 同样的section of the XML specification 特别指出&amp;#xA; 之类的字符引用确实有效:“如果未规范化的属性值包含对空白字符的字符引用,而不是空格(#x20),规范化值包含引用的字符本身”。当然,在实践中,它只会在兼容的实现中工作......
【解决方案2】:

根据Annotated XML Spec,属性值中的空格由 XML 处理器规范化(参见 3.3.3 上的 (T) 注释)。所以,看起来答案可能是否定的。

【讨论】:

  • 除非你可以控制你的 xml 处理器。
【解决方案3】:

正如其他人所指出的,XML 规范不允许在属性中保留空格。事实上,这是您可以对属性和元素所做的少数区别之一(另一个主要区别是元素可以包含其他标签,而属性则不能)。

您必须首先在 XML 之外处理文件以保留空格。

【讨论】:

  • 我认为这是误导。如果您可以控制您的 xml 处理器,那么它本身似乎是有效的并且可以保留该空白。我可以达到这个结果。
【解决方案4】:

如果你能控制你的 XML 处理器,你就可以做到。

来自我的other answer(链接了许多参考资料):

如果你有类似的 XML

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE elemke [
<!ATTLIST brush wood CDATA #REQUIRED>
]>

<elemke>
<brush wood="guy&#xA;threep"/>
</elemke>

和像

这样的 XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet  version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template name="split">
  <xsl:param name="list"      select="''" />
  <xsl:param name="separator" select="'&#xA;'" />
  <xsl:if test="not($list = '' or $separator = '')">
    <xsl:variable name="head" select="substring-before(concat($list, $separator), $separator)" />
    <xsl:variable name="tail" select="substring-after($list, $separator)" />

    <xsl:value-of select="$head"/>
    <br/><xsl:text>&#xA;</xsl:text>
    <xsl:call-template name="split">
        <xsl:with-param name="list"      select="$tail" />
        <xsl:with-param name="separator" select="$separator" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>


<xsl:template match="brush">
  <html>
  <xsl:call-template name="split">
    <xsl:with-param name="list" select="@wood"/>
  </xsl:call-template>
  </html>
</xsl:template>

</xsl:stylesheet>

你可以得到一个像这样的html:

<html>guy<br>
   threep<br>

</html>  

使用类似saxon 命令行的处理器测试/生产:

java -jar saxon9he.jar -s:in.xml -xsl:in.xsl -o:out.html

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-03-26
  • 1970-01-01
  • 2011-12-15
  • 2016-08-26
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
  • 2022-01-15
相关资源
最近更新 更多