1

[编辑:更改标题以更好地概念化问题。]

属性的值@xml:space可以是"default""preserve"。XML 指定第二个含义,但将第一个留给应用程序。(我想我是对的。)那么如果应用程序想要default实现 XSchema 的collapse呢?XSLT 1.0 如何真正做到这一点?

我认为处理文本的内置模板,即

<xsl:template match="text()">
   <xsl:value-of select="."/>
</xsl:template>

需要用类似这样的伪代码替换:

<xsl:choose>
   <xsl:when test="../@xml:space='preserve'"
     <xsl:value-of select="."/>
   </xsl:when>
   <xsl:otherwise>

      if position(.)=1 then output LTRIM(value-of(.))
      if position(.)=last() then output RTRIM(value-of(.))
      if position(.)= 1 and last()=1 then output normalize-space(.)

   </xsl:otherwise>
</xsl:choose>

然后这个输入:

<persName> The man is 
   <forename>Edward</forename>

   <forename>George</forename>
   <surname type="linked">Bulwer-Lytton</surname>, <roleName>Baron Lytton of
   <placeName>Knebworth</placeName>
   </roleName>
</persName>

将被正确渲染,就像修剪The man is Edward George Bulwer-Lytton, Baron Lytton of Knebworth前后的空间The man以及折叠和折叠之间的空间一样。(示例来自 TEI。)KnebworthEdwardGeorge

[编辑:我在这里删除了一个不正确且具有误导性的段落。]

需要为每个文本节点执行用于实现该伪代码的 XSLT 1.0。那岂不是又丑又慢?[编辑:也许不是。我简化了伪代码。有快速修剪程序吗?选择真的那么慢吗?】

底线:如何在 XSLT 1.0 中实现 XSchema 的折叠(只有浏览器嵌入的扩展)?

我希望我说的都是正确的。我希望代码很简单。我还没有看到它是怎么回事。[编辑:将 xs:collapse 更改为 XSchema 的崩溃。]

4

5 回答 5

0

这里有一些接近你想要的东西......

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>
<xsl:strip-space elements="*"/>  

<xsl:template match="/">
Demonstration of collapsed white space.
=======================================
<xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="text()">
  <xsl:value-of select="concat(normalize-space(.),' ')" />  
</xsl:template>

</xsl:stylesheet>

这会产生输出......

Demonstration of collapsed white space.
=======================================
The man is Edward George Bulwer-Lytton , Baron Lytton of Knebworth
于 2012-07-07T05:55:09.633 回答
0

你没有正确理解 的定义xml:space

它仅适用于空白文本节点。它不适用于包含在也具有非空白字符的文本节点中的空白字符(也称为“重要空白”)。

XML 1.0 规范

另一方面,在交付版本中应该保留的“重要”空白很常见,例如在诗歌和源代码中

因此,“修剪”文本节点的整个想法与xml:space.

此资源包含一个易于理解的xml:space属性说明。

更新

答案中的 OP 改变了他的初始要求。现在他想要的只是(如果我对他的答案的理解是正确的)删除所有具有相同父级的纯空白文本节点中的第一个(我也认为是最后一个)纯空白文本节点。

这很简单——只需将此模板添加到 XSLT 样式表

<xsl:template match=
   "text()[not(normalize-space())][position() = 1 or position() = last()]"/>
于 2012-07-07T14:53:29.507 回答
0

很好的编辑。谢谢迪米特。

我不相信我读错了规范,但暂时假设我是;让我修正一下我的例子(也许我应该在它来到我的时候离开)。

<persName>
   <forename>Edward</forename>
   <forename>George</forename>
   <surname type="linked">Bulwer-Lytton</surname>, <roleName>Baron Lytton of
   <placeName>Knebworth</placeName>
   </roleName>
</persName>

我希望默认处理是删除之前的纯空格文本节点,<forename>Edward</forename>而不是删除之后的纯空格文本节点<forename>Edward</forename>

但是,我也不清楚 xml:space 仅指包含或删除纯空白文本节点,例如 xsl:strip-space 就是这样。实际上,正如您所注意到的,2.10 White Space Handling 使用诗歌和源代码作为示例。这些是空间位于文本节点内的情况。@xml:space 标识应该如何处理该空间。是否应该以应用程序的默认方式保留或处理?

我认为http://www.xmlplease.com/xml/xmlspace/是错误的。

于 2012-07-07T16:51:59.320 回答
0

我在 xml-dev 进行了检查,结果证明我对 @xml:space 的含义和预期用途是正确的。

这是规范混合内容元素中的空白的代码(这是表达我想要做的更好的方式):

<xsl:template priority=".7" match="text()[position()=1 and not((ancestor::node()/@xml:space)[position()=last()]='preserve')]">
    <xsl:value-of select="normalize-space()"/>
    <xsl:if test="normalize-space(substring(., string-length(.))) = ''">
        <xsl:text> </xsl:text>
    </xsl:if>
</xsl:template>
<xsl:template priority=".7" match="text()[position()=last() and not((ancestor::node()/@xml:space)[position()=last()]='preserve')]">
    <xsl:if test="normalize-space(substring(., 1, 1)) = ''">
        <xsl:text> </xsl:text>
    </xsl:if>
    <xsl:value-of select="normalize-space()"/>
</xsl:template>
<xsl:template priority=".8" match="text()[position()=1 and position()=last() and not((ancestor::node()/@xml:space)[position()=last()]='preserve')]" >
    <xsl:value-of select="normalize-space(.)"/>
</xsl:template>

过滤@xml:space允许preserve覆盖。这test=只是测试空格的一种方法。优先级解决了当节点是元素中唯一的文本节点时引起的冲突,因此既是第一个节点也是最后一个节点。

于 2012-07-25T13:01:20.790 回答
0

基于您之前的答案...如果您有一个看起来像这样的文件

<document>
<p>A paragraph of text with subtags (whitespace after; no whitespace only between): Lorem
        <italic>Before/After</italic> dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim <italic>Before/After</italic>
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
<p>A paragraph of text with subtags (whitespace between: Lorem ipsum dolor sit amet, consectetur
    adipiscing elit, sed do eiusmod <italic>Before/After</italic>
    <italic>Before/After</italic> incididunt ut labore et dolore magna aliqua. Ut enim ad minim
    veniam, <italic>Before/After</italic> <italic>Before/After</italic> laboris nisi ut aliquip 
    ex ea commodo consequat. </p>
</document>

然后斜体标记之间的位不会被您的规范化空间模板捕获,因为它们既不在块的开头也不在块的结尾。

据我所知,您必须添加第四个来检查打开和关闭空间(并保留它),然后规范化两者之间的东西。

<xsl:template priority=".7" match="text()[not(position()=1) and not(position()=last()) 
    and not((ancestor::node()/@xml:space)[position()=last()]='preserve')]" >
    <xsl:if test="normalize-space(substring(., 1, 1)) = ''">
        <xsl:text> </xsl:text>
    </xsl:if>
        <xsl:value-of select="normalize-space()"/>
    <xsl:if test="normalize-space(substring(., string-length(.), 1)) = ''">
        <xsl:text> </xsl:text>
    </xsl:if>
</xsl:template>
于 2017-04-21T20:53:05.730 回答