如何使用 XSLT 按句子标记文本
How to tokenize text by sentences with XSLT
我的 XSLT 知识已经达到了以下问题的极限。
我有一个 XML 文件,看起来像这样,经过简化:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<p>
<w>This</w>
<w>is</w>
<w>a</w>
<w>sentence</w>
<w>with</w>
<w>a</w>
<entity type="name">Name</entity>
<w>and</w>
<w>a</w>
<entity type="place">Place</entity>
<w>etc</w>. <w>This</w>
<w>is</w>
<w>another</w>
<w>sentence</w>
<w>with</w>
<w>an</w>
<w>abbrev</w>. <w>before</w>
<w>its</w>
<w>end</w>. <w>Is</w>
<w>this</w>
<w>a</w>
<w>question</w>? <w>Sure</w>
<w>it</w>
<w>is</w>! </p>
</root>
文本已按单词标记。我需要自动标记句子。为此,我有一个变量,其中包含结束句子的可能字符:
<xsl:variable name="SEnd">.!?</xsl:variable>
所以,我需要一个 XSLT 2.0 样式表,它将:
- 遍历每个段落
- 组单词 (
<w>
) 从段落中的第一个 <w>
开始并以 <w>
元素结束,其直接兄弟 text()
节点以以下之一开始变量集 "SEnd" 的成员,但当且仅当 following-sibling::w
以大写字母开头(这必须是正则表达式 \p{Lu}
而不仅仅是 [A-Z]
因为我有多个脚本;
- 将上述各组包裹在
<s></s>
. 中
这样 <w>abbrev</w>.
就不会被识别为句子的最后一个单词,因为它后面跟着一个小写单词。
结果应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<p>
<s><w>This</w>
<w>is</w>
<w>a</w>
<w>sentence</w>
<w>with</w>
<w>a</w>
<entity type="name">Name</entity>
<w>and</w>
<w>a</w>
<entity type="place">Place</entity>
<w>etc</w>.</s>
<s><w>This</w>
<w>is</w>
<w>another</w>
<w>sentence</w>
<w>with</w>
<w>an</w>
<w>abbrev</w>. <w>before</w>
<w>its</w>
<w>end</w>.</s>
<s><w>Is</w>
<w>this</w>
<w>a</w>
<w>question</w>?</s>
<s><w>Sure</w>,
<w>it</w>
<w>is</w>!</s>
</p>
</root>
我知道这不是万无一失的,会有例外,但这对这个特定任务来说并不重要。我从概念上理解这个问题,我认为应该使用 <xsl:for-each-group>
但我不知道如何将它们实际放在一起。
非常感谢你的帮助。
一切顺利,
坦奇
怎么样:
<xsl:template match="p">
<xsl:copy>
<xsl:for-each-group select="node()" group-ending-with="text()[matches(., $SEnd)][matches(following-sibling::w[1], '^\p{Lu}')]">
<s>
<xsl:apply-templates select="current-group()" />
</s>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
我的 XSLT 知识已经达到了以下问题的极限。
我有一个 XML 文件,看起来像这样,经过简化:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<p>
<w>This</w>
<w>is</w>
<w>a</w>
<w>sentence</w>
<w>with</w>
<w>a</w>
<entity type="name">Name</entity>
<w>and</w>
<w>a</w>
<entity type="place">Place</entity>
<w>etc</w>. <w>This</w>
<w>is</w>
<w>another</w>
<w>sentence</w>
<w>with</w>
<w>an</w>
<w>abbrev</w>. <w>before</w>
<w>its</w>
<w>end</w>. <w>Is</w>
<w>this</w>
<w>a</w>
<w>question</w>? <w>Sure</w>
<w>it</w>
<w>is</w>! </p>
</root>
文本已按单词标记。我需要自动标记句子。为此,我有一个变量,其中包含结束句子的可能字符:
<xsl:variable name="SEnd">.!?</xsl:variable>
所以,我需要一个 XSLT 2.0 样式表,它将:
- 遍历每个段落
- 组单词 (
<w>
) 从段落中的第一个<w>
开始并以<w>
元素结束,其直接兄弟text()
节点以以下之一开始变量集 "SEnd" 的成员,但当且仅当following-sibling::w
以大写字母开头(这必须是正则表达式\p{Lu}
而不仅仅是[A-Z]
因为我有多个脚本; - 将上述各组包裹在
<s></s>
. 中
这样 <w>abbrev</w>.
就不会被识别为句子的最后一个单词,因为它后面跟着一个小写单词。
结果应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<p>
<s><w>This</w>
<w>is</w>
<w>a</w>
<w>sentence</w>
<w>with</w>
<w>a</w>
<entity type="name">Name</entity>
<w>and</w>
<w>a</w>
<entity type="place">Place</entity>
<w>etc</w>.</s>
<s><w>This</w>
<w>is</w>
<w>another</w>
<w>sentence</w>
<w>with</w>
<w>an</w>
<w>abbrev</w>. <w>before</w>
<w>its</w>
<w>end</w>.</s>
<s><w>Is</w>
<w>this</w>
<w>a</w>
<w>question</w>?</s>
<s><w>Sure</w>,
<w>it</w>
<w>is</w>!</s>
</p>
</root>
我知道这不是万无一失的,会有例外,但这对这个特定任务来说并不重要。我从概念上理解这个问题,我认为应该使用 <xsl:for-each-group>
但我不知道如何将它们实际放在一起。
非常感谢你的帮助。
一切顺利, 坦奇
怎么样:
<xsl:template match="p">
<xsl:copy>
<xsl:for-each-group select="node()" group-ending-with="text()[matches(., $SEnd)][matches(following-sibling::w[1], '^\p{Lu}')]">
<s>
<xsl:apply-templates select="current-group()" />
</s>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>