Java 如果定义了maxLength和模式限制,那么针对XSD验证XML对于长字符串来说很慢

Java 如果定义了maxLength和模式限制,那么针对XSD验证XML对于长字符串来说很慢,java,xsd,xml-parsing,jaxb,xsd-validation,Java,Xsd,Xml Parsing,Jaxb,Xsd Validation,我们在xsd中定义了以下简单类型: <xsd:simpleType name="SimpleText255NotBlankType"> <xsd:annotation> <xsd:documentation xml:lang="en">String of maximum 255 characters, not blank</xsd:documentation> </xsd:annotat

我们在xsd中定义了以下简单类型:

<xsd:simpleType name="SimpleText255NotBlankType">
        <xsd:annotation>
            <xsd:documentation xml:lang="en">String of maximum 255 characters, not blank</xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:string">
            <xsd:minLength value="1"/>
            <xsd:maxLength value="255"/>
            <xsd:pattern value=".*[^\s].*"/>
        </xsd:restriction>
</xsd:simpleType>

最多255个字符的字符串,不为空
问题是,当在输入xml中提供一个非常长的字符串(约1000000个字符)作为值时,我们会假定它很快会因为长度而被视为无效。实际上,由于在maxLength限制之前对正则表达式求值,验证需要几分钟的时间

如果我们这样定义simpleType,我们找到了解决问题的方法:

     <xsd:simpleType name="SimpleText255Type">
        <xsd:annotation>
            <xsd:documentation xml:lang="en">String of maximum 255 characters</xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:string">
            <xsd:minLength value="1"/>
            <xsd:maxLength value="255"/>
            <xsd:pattern value=".{1,255}"/>
        </xsd:restriction>
    </xsd:simpleType>
    <xsd:simpleType name="SimpleText255NotBlankType">
        <xsd:annotation>
            <xsd:documentation xml:lang="en">String of maximum 255 characters, not blank</xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="SimpleText255Type">
            <xsd:pattern value=".*[^\s].*"/>
        </xsd:restriction>
    </xsd:simpleType>

最多255个字符的字符串
最多255个字符的字符串,不为空
这种解决方法之所以有效,是因为XSSimpleType的Xerces实现构建了一个正则表达式模式的向量,而
{1255}
模式将首先被评估,并且失败的速度相对较快,因此不会检查耗时的第二个正则表达式

有没有人遇到过同样的问题并找到了一个解决方案,它不依赖于xsd验证的实现?或者有没有办法在jaxb中对xsd:restriction-s进行验证(以便在检查模式之前验证maxLength)

我们在github上创建了一个示例应用程序:
Xerces2支持XSD 1.1。不幸的是,该版本不在官方的maven中央存储库中。您可以使用第三方存储库(也需要icu4j)。如果它对您来说不是一个可行的解决方案,您可以从(Xerces2Java2.12.0(XMLSchema1.1))下载官方稳定版本,并将其安装到本地maven存储库中


org.opengis.cite.xerces
xercesImpl-xsd11
2.12-β-r1667115
com.ibm.icu
icu4j
4.6
您还需要替换模式版本

SchemaFactory sf=SchemaFactory.newInstance(“http://www.w3.org/XML/XMLSchema/v1.1");
您可以在XSD1.1中使用断言(XSD1.1中还有其他有用的新特性,您可以从中受益)。现在,您可以指定验证规则的评估顺序



我希望这是一个可行的解决方案,我可以帮助你

Xerces2支持XSD1.1。不幸的是,该版本不在官方的maven中央存储库中。您可以使用第三方存储库(也需要icu4j)。如果它对您来说不是一个可行的解决方案,您可以从(Xerces2Java2.12.0(XMLSchema1.1))下载官方稳定版本,并将其安装到本地maven存储库中


org.opengis.cite.xerces
xercesImpl-xsd11
2.12-β-r1667115
com.ibm.icu
icu4j
4.6
您还需要替换模式版本

SchemaFactory sf=SchemaFactory.newInstance(“http://www.w3.org/XML/XMLSchema/v1.1");
您可以在XSD1.1中使用断言(XSD1.1中还有其他有用的新特性,您可以从中受益)。现在,您可以指定验证规则的评估顺序



我希望这是一个可行的解决方案,我可以帮助你

也许有一个更好的正则表达式来测试“非空白”,比如
“^(?!\s*$)。+”
已经足够了。仅供参考:
[^\s]
写得更好,因为
\s
没有指定
冗余?删除可能很好的
@thomas kläger,但不幸的是XSD中的正则表达式验证是有限的,并且不支持lookaheads(),因此我们不能使用该正则表达式。@andreas由于该模式确实是多余的,因此需要它,因为没有它,限制的求值顺序将是:1。“*[^\s].*”(慢,有效)2.maxLength(无效)。将长度定义为父类型上的一个单独的正则表达式,正则表达式将是第一个得到评估的正则表达式,并且很快失败,这就是为什么该解决方案可以是一个单独的正则表达式,对于测试像
“^(?!\s*$)这样的“非空白”可能是一个更好的正则表达式。+”
已经足够了。仅供参考:
[^\s]
写得更好,因为
\S
没有指定与
冗余的
?删除可能很好的
@thomas kläger,但不幸的是XSD中的正则表达式验证是有限的,并且不支持lookaheads(),因此我们不能使用该正则表达式。@andreas由于该模式确实是多余的,因此需要它,因为没有它,限制的求值顺序将是:1。“*[^\s].*”(慢,有效)2.maxLength(无效)。将长度定义为父类型上的一个单独的正则表达式,正则表达式将是第一个被评估的,并且很快就会失败,这就是为什么解决方法可能是一个孤立的问题