2014-02-10 26 views
0

我需要使用XmlBeans针对在以下XSD中声明的(复杂)类型验证以下XML。XmlBeans - 针对某个类型的XSD验证,而不是元素

我的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验证。但验证失败,消息"Invalid type"对元素“参数”。只有通过在XSD中取消注释“Param”元素声明并在XML中添加名称空间前缀p1:来更改XML中的“Param”的名称空间之后,验证才能成功 - 即在对元素声明进行验证时,不是对类型声明。

我需要的是:

  1. 使用XMLBeans
  2. 莫名其妙地告诉它XmlBeans的是,在XML根元素"{http://www.xxx.com/xmlns/osb/WS2CICS/Envelope/v01}Param"是OK(不需要检查)。
  3. 告诉XmlBeans的根是复杂类型"{http://www.xxx.com/xmlns/osb/WS2CICS/program/PROG1/p1}ParamType"的(检查儿童)

我该怎么做呢?

背景:

我有一个邮件信封里的“参数”元件的类型是“anyType的”,即,它可以具有任何内容。在特定情况下,我需要检查“Param”是否具有由动态选择的XSD提供的特定内容。我可以很容易地检查信封的有效性,但在第二步中,我需要检查Param的有效性。

编辑:重新表述

回答

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,但人们通常会用一个文件对象,而不是。 在实现中,使用DOM可能不是最优的,但是 - 如果我新的XmlBeans更好,代码可以改进。

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()) }; 
... 

当导入root.xsd内input.xsd,你需要正确的指向root.xsd。如果你发现问题,你可以使用root.xsd的绝对路径。

+0

通过实验我找到了同样的解决方案 - 除了在代码中动态内联生成元素“Param”的模式外。但是,不知何故,我希望会有更好的解决方案 - 这样XmlBeans将只验证“Param”元素的内容,而不是元素本身,这将删除“Param”元素的模式必要性。 loader.parse(...)方法有一个SchemaType作为第二个参数。但是我没有成功地使它工作。也许这将是方式? – xarx

+0

基本上,您要求验证xml的某些部分,但不包括其他部分。我不确定你是否可以做到这一点。 – IndoKnight

+0

关于我原来问题中的“背景”评论,你会如何解决这个问题?你会使用你在答案中建议的解决方案吗? – xarx