Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java正则表达式匹配器在BMP之外断开字符_Java_Regex_Xml_Supplementary - Fatal编程技术网

Java正则表达式匹配器在BMP之外断开字符

Java正则表达式匹配器在BMP之外断开字符,java,regex,xml,supplementary,Java,Regex,Xml,Supplementary,我目前正在编写一个util类来清理输入,该类保存到xml文档中。对我们来说,清理意味着所有非法字符()都将从字符串中删除 我试图通过使用一些正则表达式来实现这一点,它将所有无效字符替换为空字符串,但对于BMP之外的unicode字符,这似乎以某种方式破坏了编码,留给我的是那些?字符。用regexp替换的方式似乎也无关紧要(String#replaceAll(String,String),Pattern#compile(String),org.apache.commons.lang3.RegExU

我目前正在编写一个util类来清理输入,该类保存到xml文档中。对我们来说,清理意味着所有非法字符()都将从字符串中删除

我试图通过使用一些正则表达式来实现这一点,它将所有无效字符替换为空字符串,但对于BMP之外的unicode字符,这似乎以某种方式破坏了编码,留给我的是那些
字符。用regexp替换的方式似乎也无关紧要(
String#replaceAll(String,String)
Pattern#compile(String)
org.apache.commons.lang3.RegExUtil#removeAll(String,String)

下面是一个带有测试的示例实现(在Spock中),它显示了问题: XmlStringUtil.java

package com.example.util;

import lombok.NonNull;

import java.util.regex.Pattern;

public class XmlStringUtil {

    private static final Pattern XML_10_PATTERN = Pattern.compile(
        "[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\x{10000}-\\x{10FFFF}]"
    );

    public static String sanitizeXml10(@NonNull String text) {
        return XML_10_PATTERN.matcher(text).replaceAll("");
    }

}
XmlStringUtilSpec.groovy

package com.example.util

import spock.lang.Specification

class XmlStringUtilSpec extends Specification {

    def 'sanitize string values for xml version 1.0'() {
        when: 'a string is sanitized'
            def sanitizedString = XmlStringUtil.sanitizeXml10 inputString

        then: 'the returned sanitized string matches the expected one'
            sanitizedString == expectedSanitizedString

        where:
            inputString                                | expectedSanitizedString
            ''                                         | ''
            '\b'                                       | ''
            '\u0001'                                   | ''
            'Hello World!\0'                           | 'Hello World!'
            'text with emoji \uD83E\uDDD1\uD83C\uDFFB' | 'text with emoji \uD83E\uDDD1\uD83C\uDFFB'
    }

}
我现在有了一个解决方案,从单个代码点重建整个字符串,但这似乎不是正确的解决方案


提前谢谢

没有正则表达式的解决方案可能是经过过滤的代码点流:

publicstaticstringsanitize\uxml\u10(字符串输入){
返回input.codePoints()
.filter(测试::allowedXml10)
.collect(StringBuilder::new、StringBuilder::appendCodePoint、StringBuilder::append)
.toString();
}
私有静态布尔允许XML10(int代码点){
如果(0x0009==codepoint)返回true;
如果(0x000A==codepoint)返回true;
如果(0x000D==codepoint)返回true;

如果(0x0020不带正则表达式的解决方案可能是经过过滤的代码点流:

publicstaticstringsanitize\uxml\u10(字符串输入){
返回input.codePoints()
.filter(测试::allowedXml10)
.collect(StringBuilder::new、StringBuilder::appendCodePoint、StringBuilder::append)
.toString();
}
私有静态布尔允许XML10(int代码点){
如果(0x0009==codepoint)返回true;
如果(0x000A==codepoint)返回true;
如果(0x000D==codepoint)返回true;

如果(0x0020经过一些读取和实验后,对正则表达式进行轻微更改(将
\x{..}
替换为代理项
\u..\u...
有效:

private静态最终模式XML\u 10\u Pattern=Pattern.compile(
“[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\uD800\uDC00-\uDBFF\uDFFF]”
);
检查:

sanitizeXml10(“\uD83E\uDDD1\uD83C\uDFFB”).codePoints().mapToObj(Integer::toHexString).forEach(System.out::println);
导致

1f9d1
1f3fb

经过一些阅读和实验后,对Regex稍作修改(将
\x{..}
替换为代理项
\u..\u..
有效:

private静态最终模式XML\u 10\u Pattern=Pattern.compile(
“[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\uD800\uDC00-\uDBFF\uDFFF]”
);
检查:

sanitizeXml10(“\uD83E\uDDD1\uD83C\uDFFB”).codePoints().mapToObj(Integer::toHexString).forEach(System.out::println);
导致

1f9d1
1f3fb

根据,正则表达式应该使用“外部”字符。你确定这不仅仅是字体问题吗?我也这么认为(一开始),但测试结果有所不同。where块的最后一个条目失败。这些表情符号属于D7FF和E000之间的禁止范围,应该根本无法通过。如果我在它们周围插入空格,那么结果只会是空格。因此Java在一起写入时对字符串的解释不同。甚至打印cod
“\uD83E\uDDD1\uD83C\uDFFB”
中的epoint显示
0x1f9d1
0x1f3fb
。emojis是有效的XML。正如您在第二篇文章中所述,它们在允许的范围0x10000到0x10FFFF之间。这也在Wikipedia文章中有说明。根据和正则表达式应与“outside”一起使用字符。你确定这不仅仅是字体问题吗?我也这么认为(一开始),但测试结果有所不同。where块的最后一个条目失败。这些表情符号属于D7FF和E000之间的禁止范围,应该根本无法通过。如果我在它们周围插入空格,那么结果只会是空格。因此Java在一起写入时对字符串的解释不同。甚至打印cod
“\uD83E\uDDD1\uD83C\uDFFB”中的epoint
显示了
0x1f9d1
0x1f3fb
。emojis是有效的XML。正如您在第二篇文章中所述,它们在允许的范围0x10000到0x10FFFF之间。这在维基百科文章中也有说明。是的,这基本上就是我所做的。它是有效的。但奇怪的是,在字符串级别上已经不可能做到这一点了。耶啊,这基本上就是我所做的。它是有效的。但感觉很奇怪,在字符串级别上已经不可能这样做了。好的,基本上就是这样。奇怪的是,我必须从字符点组中删除所有转义,但不允许从单个字符点中删除它们。所以工作的正则表达式是
[^\u0009\u000A\u000D-퟿-�好的,基本上就是这样。奇怪的是,我不得不从字符点组中删除所有转义符,但不允许从单个字符点中删除它们。因此工作正则表达式是
[^\u0009\u000A\u000D-퟿-�