2014-02-10 25 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