[编辑:更改了标题以更好地概念化问题。
属性@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
之前和之后的空间修剪Knebworth
,并且Edward
和George
之间的空间折叠。(该示例来自 TEI。
[编辑:我在这里删除了一个不正确和误导性的段落。
实现该伪代码的 XSLT 1.0 需要为每个文本节点执行。那岂不是又丑又慢?[编辑:或者也许不是。我简化了伪代码。有快速修剪程序吗?选择真的那么慢吗?
底线:如何在XSLT 1.0中实现XSchema的崩溃(仅使用浏览器嵌入式扩展(?
我希望我说的都是对的。我希望代码很简单。我还没有看到它是如何做到的。[编辑:将xs:collapse更改为XSchema的崩溃。
这是接近您想要的东西...
<?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
编辑得好。谢谢迪米特雷。
我不相信我读错了规范,但假设我读错了;让我修复我的例子(也许我应该离开它来找我(。
<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 空白处理使用诗歌和源代码作为示例。这些是空间位于文本节点内的情况。@xml:space 标识应如何处理该空间。是否应该保留它或以应用程序的默认方式处理它?
我认为 http://www.xmlplease.com/xml/xmlspace/在这方面是错误的。
你还没有正确理解xml:space
的定义。
它仅适用于仅空格文本节点。它不适用于包含在也具有非空格字符的文本节点中的空格字符(也称为"重要空格"(。
从 XML 1.0 规范:
">另一方面,"重要"的空白应该是 保存在交付版本中很常见,例如在诗歌中 和源代码">
因此,"修剪"文本节点的整个想法与xml:space
无关。
此资源包含易于理解的 xml:space
属性说明。
更新:
答案中的OP改变了他最初的要求。现在他想要的只是(如果我对他的答案的理解是正确的(删除具有相同父级的所有纯空格文本节点中的第一个(我也认为最后一个(仅空格文本节点。
这很简单 -- 只需将此模板添加到 XSLT 样式表中:
<xsl:template match=
"text()[not(normalize-space())][position() = 1 or position() = last()]"/>
我在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=
只是测试空格的一种方式。优先级解决了当节点是元素中唯一的文本节点(因此是第一个和最后一个(时引起的冲突。
建立在你之前的答案之上...如果您有如下所示的文件
<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>