如何使用 XSLT 3.1 "replace" 函数在括号外用逗号删除另一个数字后的数字

How to remove a number after another number with comma outside parentheses using XSLT 3.1 "replace" function

我用逗号查找多于两个的数字,但我的正则表达式查找括号内或括号外的数字。如何查找不在括号内的数字。

使用正则表达式

([0-9]+, ){2,}

字符串

Albemarle Paper Co. v Moody (1975) 422 US 405, 425, 95 S Ct 2362

预期结果

Albemarle Paper Co. v Moody (1975) 422 US 405, 95 S Ct 2362

特别是我的XML长得像

<root>
<p><styled-content><italic>Agarwal v Johnson </italic>(1979) 25 C3d 932, 942, overruled on *6 other grounds in <italic>White v Ultramar, Inc.</italic> (1999) 21 C4th 563</styled-content></p>
</root>

这是带有正则表达式和替换功能的 XSL 模板:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="xml" indent="yes"/>

    <xsl:template match="root">
        <xsl:copy>
            <p><xsl:value-of select="replace(p/styled-content, '[0-9]+(?:, [-0-9]+)+,(?![^()]*\))', '')"/></p>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

注意:现在,您添加了 XSD 标签,注意您不能在 XML Schema regex 中使用前瞻:“特别值得注意的是完全没有锚点,如插入符号和美元、单词边界和环视。”。

XML 架构 1.1 支持 xs:assertions。使用以下内容,您可以确保 123, 345, 567 text 匹配,而 (123, 345, 567) text(123, 345, 567) 123, 345, 567 text 不匹配:

<xs:element name="your_element">
  <xs:simpleType>
    <xs:restriction base="xs:string">
      <xs:assertion test="not(matches($value, '.*\([^()]*([0-9]+, ){2,}[^()]*\).*'))"/>
      <xs:assertion test="matches($value, '.*([0-9]+, ){2,}.*')"/>
    </xs:restriction>
  </xs:simpleType>
</xs:element>

以下答案适用于其他使用前瞻的引擎:

[0-9]+(?:, [-0-9]+)+(?![^()]*\))

参见proof。它将找到逗号分隔的数字序列,后面没有非括号字符,直到右括号。

如果逗号必须跟在第二个或更多数字之后,只需添加:

[0-9]+(?:, [-0-9]+)+,(?![^()]*\))
                    ^
                    |___ HERE

updated demo

如果正则表达式引擎支持 (*SKIP)(*FAIL),那么这个正则表达式可以更好地确保数字不在括号内:

(?x)                    # Verbose flag
    (?:\([^()]*)        # Match '( ....'
    (?:\d+,\ ){2,}      # Our regex in '( ..... )'
    (?:[^()]*\))        # Match  '..... )'
    (*SKIP)(*FAIL)      # Fail the first alternative
|                       # Second alternative
    (?:\d+,\ ){2,}      # Our regex not enclosed in '( ... )'

See Regex Demo

旧解

当出现正则表达式问题时,OP 应该说明所使用的语言,因为不同的 (1) 不同的语言支持正则表达式规范的不同子集,并且 (2) 根据问题的复杂性,它可能take more 使用一些程序代码来完全解决问题或至少以简单的方式解决问题。

目前提出的方案都没有完全解决判断数字是否被括号括起来的问题。他们采用一种简化的方法来查看数字后是否跟有右括号,这会导致错误的结果。

解决方案是使用一个正则表达式来查找两个替代的子正则表达式模式:(1) 括号内的数字和 (2) 数字,然后确定哪个子模式匹配,并且只使用秒数中的匹配项子模式。这里我使用 Python:

import re

text = """Albemarle Paper Co. v Moody (1975) 422 US 405, 425, 95 S Ct 2362 (Booboo)
Albemarle Paper Co. v Moody (1975) 422 US 405, 95 S Ct 2362
Aerotek, Inc. v Johnson Group Staffing Co. (July 30, 2013, C067652) 2013 Cal Unpub Lexis 5424:"""

r_ex = re.compile(r"""
        (?:\([^)]*)             # Match '( ....'
        (?P<R1>(\d+,\s){2,})    # Our regex in capture group R1
        (?:[^)]*\))             # Match  '..... )'
    |                           # Second alternative
        (?P<R2>(\d+,\s){2,})    # Our regex not enclosed in '( ... )' in capture group R2
        """, flags=re.X)

for m in r_ex.finditer(text):
    if m.lastgroup == 'R2': # only chose second alternative matches
        print(m.group())

打印:

405, 425,

更新

当我写这篇文章时,OP 似乎确实添加了一种语言,xsd,它可能不提供程序代码。无论如何,我都会留下这个答案。

看来您正在使用 XSLT 3.1 replace function

您可以使用

<xsl:value-of select="replace(styled-content, '(\([^()]*\))|([0-9]+,)\s*[0-9]+,', '')"/>

这是一个demo of how the replace works in this case

详情

  • (\([^()]*\)) - 捕获第 1 组(替换模式中的 </code>):<code>(,除 ) 和 [=14= 之外的任何 0+ 个字符] 然后 )
  • | - 或
  • ([0-9]+,) - 捕获第 2 组 (</code>):1+ 位数字和逗号 </li> <li><code>\s* - 0+ 个空格
  • [0-9]+ - 1+ 位数
  • , - 一个逗号。

替换为第1组和第2组的内容