gpt4 book ai didi

java - Xerces-J 对未解析的 xsi :type? 的宽松验证失败是否正确

转载 作者:行者123 更新时间:2023-11-30 07:27:41 25 4
gpt4 key购买 nike

我在使用这段代码(如下)验证此 SOAP Envelope 时遇到问题。

我得到的错误是:

org.xml.sax.SAXParseException; cvc-elt.4.2: Cannot resolve 'ipo:UKAddress' to a type definition for element 'shipTo'.

SOAP XSD 将 Body 定义为:

<xs:complexType name="Body">
<xs:sequence>
<xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xs:sequence>

我的期望是“lax”应该验证它是否有定义,但如果没有定义则忽略。但是,xsi:type="ipo:UKAddress" 的情况并非如此。我只验证 SOAP Envelope - 而不是 Body

它看起来像是 xerces-j 中的一个错误。在同一代码块中,XMLSchemaValidator.java :2152 在引发错误之前实际上检查了 processContents:

else if (wildcard != null && wildcard.fProcessContents == XSWildcardDecl.PC_STRICT) {

鉴于,XMLSchemaValidator.java :2178 没有进行这样的检查,无论如何都会抛出。

fCurrentType = getAndCheckXsiType(element, xsiType, attributes);

对我来说,它看起来像是 xerces-j 中的一个错误。另外,Java 8 中也存在这个问题。如果有任何帮助或确认这确实是一个错误,我们将不胜感激。

package com.example.xmlvalidate;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.CodeSource;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class Validate {
private static final String envelope =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<soapenv:Envelope \n" +
" xmlns=\"http://www.w3.org/2001/XMLSchema\"" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
" >\n" +
" <soapenv:Body>\n" +
" <ipo:purchaseOrder xmlns:ipo=\"http://www.example.com/IPO\">\n" +
" <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">\n" +
" <name>Helen Zoe</name>\n" +
" <street>47 Eden Street</street>\n" +
" <city>Cambridge</city>\n" +
" <postcode>CB1 1JR</postcode>\n" +
" </shipTo>\n" +
" </ipo:purchaseOrder>\n" +
" </soapenv:Body>\n" +
"</soapenv:Envelope>";

private static final String SOAP_1_1_ENVELOPE =
"http://schemas.xmlsoap.org/soap/envelope";
protected static final String W3C_XML_SCHEMA =
"http://www.w3.org/2001/XMLSchema";

public static void validate() throws ParserConfigurationException, SAXException, IOException, TransformerException {
final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setValidating(false);

final Class<?> clazz = documentBuilderFactory.getClass();
final CodeSource source = clazz.getProtectionDomain().getCodeSource();
System.out.println("Document builder implementation: " + clazz.getName() + " from : " + (source == null ? "JRE" : source));

final DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
final InputStream is = new ByteArrayInputStream(envelope.getBytes(StandardCharsets.UTF_8));
final Document document = documentBuilder.parse(is);
final DOMSource domSource = new DOMSource(document);

final StreamSource streamSource = new StreamSource(new URL(SOAP_1_1_ENVELOPE).openStream());
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
final Schema schema = schemaFactory.newSchema(streamSource);

final Validator validator = schema.newValidator();
validator.validate(domSource);
}
}

最佳答案

简短回答:在这种情况下,Xerces 要么毫无疑问是正确的,要么不能证明是错误的。

长答案:

您没有指定您使用的是 XSD 1.0 还是 XSD 1.1。

在 1.0 中,规范对于 xsi:type 属性(其 QName 值未解析为架构中的类型定义)的有效性的影响有些不清楚。验证规则的一种自然阅读:3.3.4 中的模式有效性评估(元素)是当xsi:type发生时,它必须解决(注意文本中一致性要求和有效性要求之间的轻微混淆)。该规则的另一种解读是,如果验证规则的第 1.2.1.2.3 条不适用,那么显然第 1.2.1.2、1.2 和 1 条也不适用,这得出的结论是该元素应该是宽松的评估。

相同的两个读数适用于同一部分中的“验证规则:元素本地有效(元素)”的第 4.2 条。该子句表示 xsi:type 的值“必须解析为类型定义”,这意味着如果 xsi:type 值未解析,则该元素无效,或者(根据对规则的不同解读)该元素无效如果该元素显然不是(已知)针对指示的类型在本地有效。

在 1.1 中,规则已被重写并且可能变得更加清晰。如果 xsi:type 的值是无法解析为类型定义的 QName,则会计算回退类型,并根据回退类型验证该元素;在您想到的情况下,该类型将是 xsd:anyType。但 1.1 也非常明确地指出,在这种情况下,xsi:type 属性本身无效(验证规则的第 5 条:3.2.4 中的属性本地有效。

因此,根据 XSD 1.1 的规则,很明显 Xerces 正确地将输入标记为无效,尽管错误代码可能更合理的是不同的代码。

如果您使用的是 XSD 1.0,从错误代码中可以清楚地看出,Xerces 正在获取非解析 xsi:type 值的第一个 View ,并将其视为有效性错误。我认为很难从规范文本中证明这是唯一可能的解释,但要证明它是错误的就更难了:这显然是对规范的合理解释。如果您希望忽略 xsi:type 的问题并且不将其视为有效性错误,则需要使用跳过通配符,而不是宽松的通配符。 (当然,您可以为 SOAP 负载声明您自己的元素包装器,在其内容模型中使用跳过通配符进行声明,从而强制执行您想要的验证行为。)

关于java - Xerces-J 对未解析的 xsi :type? 的宽松验证失败是否正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36592309/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com