我需要使用XmlBeans对以下XSD中声明的(复杂)类型验证以下XML。
我的XSD:
<xs:schema targetNamespace="http://www.xxx.com/xmlns/osb/WS2CICS/program/PROG1/p1" attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns="http://www.xxx.com/xmlns/osb/WS2CICS/program/PROG1/p1"
xmlns:ct="http://www.xxx.com/xmlns/osb/WS2CICS/common"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!--xs:element name="Param" type="ParamType"/-->
<xs:complexType name="ParamType">
<xs:sequence>
<xs:element name="Text" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
我的XML:
<Param xsi:type="p1:ParamType"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.xxx.com/xmlns/osb/WS2CICS/Envelope/v01"
xmlns:p1="http://www.xxx.com/xmlns/osb/WS2CICS/program/PROG1/p1">
<p1:Text>abc</p1:Text>
</Param>
我基本上使用this site中的代码来使用XmlBeans进行XML验证。但验证失败,并且元素“Param”的消息为"Invalid type"
。只有在XSD中取消注释“Param”元素声明并在通过向其添加命名空间前缀p1:
来更改XML中的“Param”命名空间之后,验证才会成功 - 即在对元素声明进行验证时,不是类型声明。
我需要的是:
"{http://www.xxx.com/xmlns/osb/WS2CICS/Envelope/v01}Param"
是否正常(无需检查)。"{http://www.xxx.com/xmlns/osb/WS2CICS/program/PROG1/p1}ParamType"
(检查孩子)我该怎么做?
背景:
我有一个消息信封,其中“Param”元素的类型为“anyType”,即它可以包含任何内容。在特定情况下,我需要检查“Param”是否具有由动态选择的XSD给出的特定内容。我可以很容易地检查信封的有效性,但在第二步中,我还需要检查Param的有效性。
编辑:重新措辞
答案 0 :(得分:1)
您需要记住,XSD架构文件只能有一个目标命名空间。你在这里要做的是在命名空间http://www.example.com/xmlns/osb/WS2CICS/program/PROG1/p1中定义complexType'ParamType',在命名空间http://www.example.com/xmlns/osb/WS2CICS/Envelope/v01中定义'param'元素。您应该使用两个xsd模式(导入另一个)并更改您的XMLValidator类以获取其他xsd文件输入,如下所示 -
input.xsd -
<xs:schema targetNamespace="http://www.example.com/xmlns/osb/WS2CICS/Envelope/v01" attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:p1="http://www.example.com/xmlns/osb/WS2CICS/program/PROG1/p1"
xmlns="http://www.example.com/xmlns/osb/WS2CICS/program/PROG1/p1"
xmlns:ct="http://www.example.com/xmlns/osb/WS2CICS/common"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import namespace="http://www.example.com/xmlns/osb/WS2CICS/program/PROG1/p1 root.xsd"/>
<xs:element name="Param" type="ParamType"/>
</xs:schema>
root.xsd -
<xs:schema targetNamespace="http://www.example.com/xmlns/osb/WS2CICS/program/PROG1/p1" attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns="http://www.example.com/xmlns/osb/WS2CICS/program/PROG1/p1"
xmlns:ct="http://www.example.com/xmlns/osb/WS2CICS/common"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="ParamType">
<xs:sequence>
<xs:element name="Text" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
XMLValidator -
...
public boolean validate(File dataFile, File schemaFile, File schemaFile2) {
...
...
XmlObject[] schemas = { XmlObject.Factory.parse(schemaFile,
new XmlOptions().setLoadLineNumbers()
.setLoadMessageDigest()), XmlObject.Factory.parse(schemaFile2,
new XmlOptions().setLoadLineNumbers()
.setLoadMessageDigest()) };
...
在input.xsd中导入root.xsd时,需要正确指向root.xsd。如果发现问题,可以使用root.xsd的绝对路径。
答案 1 :(得分:0)
我找不到使用XmlBeans如何针对XSD类型验证元素的直接方法。但是我通过为缺少的元素声明动态创建模式找到了一种解决方法:
/**
* Validates an XML element (it needs not be the document root) against a type declared in an XSD-schema.
*
* @param xmlObject XML element being validated
* @param schemas compiled XML schema(s) used for the validation
* @param xmlObjectType Qualified name of the schema type in <code>schemas</code> against which the element validation is performed
* @throws XmlException thrown in case of a parsing or validation error
*/
public static void validate(XmlObject xmlObject, SchemaTypeSystem schemas, QName xmlObjectType) throws XmlException {
Node node = xmlObject.getDomNode();
//..... some argument checking here .....
String elemName = node.getLocalName();
String elemNamespace = node.getNamespaceURI();
String typeName = xmlObjectType.getLocalPart();
String typeNamespace = xmlObjectType.getNamespaceURI();
String schemasKey = elemName+"@"+elemNamespace +"," +typeName+"@"+typeNamespace; //perhaps it's sufficient
// Prepare schema
SchemaTypeSystem loader = schemas;
SchemaGlobalElement schemaElem = loader.findElement(new QName(elemNamespace, elemName));
if (schemaElem != null) {
QName elemQName = schemaElem.getType().getName();
if (!elemQName.getLocalPart().equals(typeName) || !elemQName.getNamespaceURI().equals(typeNamespace))
throw new IllegalArgumentException("Requested type " +typeName+"@"+typeNamespace
+" of xmlObject is different from its actual type " +elemQName.getLocalPart()+"@"+elemQName.getNamespaceURI() +" in provided schema(s)");
}
else {
//the schema does not contain the xmlObject element declaration => add it (artificially)
String helperSchema = ""
+ "<xs:schema attributeFormDefault=\"unqualified\" elementFormDefault=\"qualified\"\n"
+ " targetNamespace=\"" +elemNamespace +"\"\n"
+ " xmlns=\"" +elemNamespace +"\"\n"
+ " xmlns:t=\"" +typeNamespace +"\"\n"
+ " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+ "\n"
+ " <xs:element name=\"" +elemName +"\" type=\"t:" +typeName +"\"/>\n"
+ "\n"
+ "</xs:schema>\n";
loader = XmlBeans.compileXsd(schemas, // extend the schema
new XmlObject[]{
XmlObject.Factory.parse(helperSchema, new XmlOptions().setLoadLineNumbers().setLoadMessageDigest()
.setDocumentSourceName(schemasKey))
}, null,
new XmlOptions().setErrorListener(null).setCompileDownloadUrls().setCompileNoPvrRule());
}
// validate the element using the loader in a standard way
// (see the link above, for instance)
validate(xmlObject, loader);
}
我在输入上收到一个XmlObject,但通常会使用File对象。 在实现中,求助于DOM可能并不是最佳的 - 如果我更好地使用新的XmlBeans,则可以改进代码。