标记直到下一次出现数据
Posted
技术标签:
【中文标题】标记直到下一次出现数据【英文标题】:Tokenizing until next occurrence of data 【发布时间】:2021-11-21 01:21:57 【问题描述】:我有一个这样的字符串:
AA 12345678910
BB 测试测试
BB 测试测试
BB 测试测试
CC 测试
AA 0897654321
BB 测试测试
CC 测试
我将如何按数据 AA 分组?顺便说一句,这只是字符串。 我可以通过定位来做到这一点,但数据 BB 是多次出现的。
是否可以标记一大块字符串。一句话:“按AA分组,直到出现另一个AA”
【问题讨论】:
那么分组的结果是什么? 像这样:AA
会在一行的开头?
@MartinHonnen 是的
【参考方案1】:
假设这个输入:
<input>
AA 12345678910
BB TESTTESTTEST
BB TESTTESTTEST
BB TESTTESTTEST
CC TEST
AA 0897654321
BB TESTTESTTEST
CC TEST
</input>
还有这个 XSLT
<xsl:for-each select="tokenize(input, '^AA ', 'm')">
<xsl:if test="normalize-space()">
<block>AA <xsl:value-of select="." /></block>
</xsl:if>
</xsl:for-each>
我们得到两个块:
<block>AA 12345678910
BB TESTTESTTEST
BB TESTTESTTEST
BB TESTTESTTEST
CC TEST
</block><block>AA 0897654321
BB TESTTESTTEST
CC TEST
</block>
tokenize()
在分隔符处拆分输入字符串,但在处理过程中会删除分隔符。这就是为什么我们需要在输出中手动添加'AA '
。
【讨论】:
如果输入是:AA12345678910,代码会有什么不同吗? 'm' 是什么意思? 当您考虑一下时,您将看到针对这种情况在正则表达式中要更改的内容。m
是多线开关。它将^
(和$
)的含义从“字符串的开始(结束)”更改为“行的开始(结束)”。这样,仅考虑位于行首的AA
,而不是当它们随机出现在其他任何地方时。您可以使用regex101.com 来处理输入中实际存在的数据。 (对于您的下一个问题:始终按原样粘贴您的输入 XML,模糊的描述和任意更改总是会导致答案不适合您的问题。)【参考方案2】:
在 XSLT 3(自 2017 年起支持,Saxon 9.8 及更高版本、Saxon-JS 2、Altova XML 2017 R3 及更高版本)中,您可以在字符串序列上使用for-each-group group-starting-with
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output indent="yes"/>
<xsl:template match="data">
<xsl:copy>
<xsl:for-each-group select="tokenize(., '\n')[normalize-space()]" group-starting-with=".[starts-with(., 'AA')]">
<group pos="position()">
<xsl:apply-templates select="current-group()"/>
</group>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match=".[. instance of xs:string]">
<xsl:element name="substring(., 1, 2)"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/6qaHaS5
在 XSLT 2 中,与上述类似使用 for-each-group
的一种方法是首先将文本行转换为 XML 元素。
【讨论】:
以上是关于标记直到下一次出现数据的主要内容,如果未能解决你的问题,请参考以下文章