2012-07-27 132 views
4

問題: 我們有幾種服務可通過XSLT生成大量的XML。我們沒有任何XSD。我花時間創建了XSD並想確認它們是正確的。目前我正在嘗試驗證XSD和XML是否正確驗證。對Java中的xsd進行XML驗證

問題: 我有一個導入到所有xsd的xsd(common.xsd)。它尚未公開託管,所以直到最近我發現將common.xsd的完整路徑放在AccountList.xsd中,我才能夠進一步獲得。我現在收到以下內容:

org.xml.sax.SAXParseException; lineNumber: 9; columnNumber: 70; s4s-att-invalid-value: Invalid attribute value for 'type' in element 'element'. Recorded reason: UndeclaredPrefix: Cannot resolve 'common:response' as a QName: the prefix 'common' is not declared.

我不知所措。我找不到在論壇或源代碼片段中獲得成功的例子。我很感謝任何幫助,以獲得這個成功驗證我的XML。

common.xsd

<xs:schema version="1.0" elementFormDefault="qualified" attributeFormDefault="unqualified" 
     xmlns="http://www.myorg.com/xsd/gen_fin" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://www.myorg.com/xsd/gen_fin"> 
    <xs:complexType name="response"> 
     <xs:sequence> 
      <xs:element name="code" type="xs:string"/> 
      <xs:element name="description" type="xs:string"/> 
     </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

AccountList.xsd

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 

<xs:schema version="1.0" elementFormDefault="qualified" attributeFormDefault="unqualified" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      xmlns:tns="http://www.myorg.com/xsd/accList" 
      targetNamespace="http://www.myorg.com/xsd/accList" 
      xmlns:common="http://www.myorg.com/xsd/gen_fin"> 
    <xs:import namespace="http://www.myorg.com/xsd/gen_fin" 
       schemaLocation="/home/me/dev/projects/svn/myorg/xsd/src/main/resources/bg/gen_resp/common.xsd"/> 

    <xs:element name="fundamo"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="response" type="common:response" minOccurs="1" maxOccurs="1"/> 
       <xs:element name="transaction" type="tns:transaction" minOccurs="0" maxOccurs="1"/> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 

    <xs:complexType name="transaction"> 
     <xs:sequence> 
      <xs:element name="transactionRef" type="xs:string"/> 
      <xs:element name="dateTime" type="xs:string"/> 
      <xs:element name="userName" type="xs:string"/> 
     </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

Test.java

final InputStream commonXsdStream = getXsd(BG_GEN_RESP_XSD_PATH, COMMON); 

ClassPathResource fullXsdListing = new ClassPathResource(BG_GEN_RESP_XSD_PATH); 

File[] allXsds = fullXsdListing.getFile().listFiles(); 

for (File currentXsd : allXsds) { 
    final int filenameLength = currentXsd.getName().length(); 
    final String filenameSanExt = currentXsd.getName().substring(0, filenameLength - 4); 

    if (!IGNORE.contains(filenameSanExt)) { 
     final InputStream xsltStream = getXslt(BG_GEN_RESP_XSLT_PATH, filenameSanExt); 
     final InputStream xsdStream = getXsd(BG_GEN_RESP_XSD_PATH, filenameSanExt); 

     TransformerFactory xmlTransformer = TransformerFactory.newInstance(); 
     Templates xsltTemplate = xmlTransformer.newTemplates(new StreamSource(xsltStream)); 
     final XSLToXMLConvertor converter = new XSLToXMLConvertor(); 
     String generatedXml = converter.getXML(inputData, xsltTemplate); 

     LOG.info(generatedXml); 

     SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
     Schema schema = schemaFactory.newSchema(lnew StreamSource(xsdStream)); 

     Validator validator = schema.newValidator(); 
     validator.validate(new StreamSource(new StringReader(generatedXml))); 

     /* 
     DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); 
     docBuilderFactory.setNamespaceAware(true); 
     docBuilderFactory.setValidating(true); 

     DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); 
     docBuilder.parse(new InputSource(new ByteArrayInputStream(generatedXml.getBytes("utf-8")))); 
     */ 
     } 
    } 
} 
+0

如果您將'targetNamespace'添加到'AccountList.xsd',它有幫助嗎? – davidfmatheson 2012-07-27 12:56:31

+0

我試過,但我收到:錯誤:src-resolve.4.2:錯誤解析組件'交易'。檢測到'transaction'在命名空間'accList'中,但該命名空間的組件不能從模式文檔'file:/ home/me/dev/projects/myorg/xsd/src/main/resources/gen_resp/AccountList中引用的.xsd」。如果這是不正確的名稱空間,則可能需要更改「事務」的前綴。如果這是正確的名稱空間,則應將相應的「導入」標記添加到「file:/home/me/dev/projects/myorg/xsd/src/main/resources/gen_resp/AccountList.xsd」中。 – user243773 2012-07-27 13:24:10

+0

看起來像添加了'targetNamespace =「...」'和'xmlns:accList =「...」'。取出'accList',也許從公共的'xmlns =「http://www.myorg.com/xsd/gen_fin」'。你可以編輯你的原始問題以反映你正在改變的內容嗎? – davidfmatheson 2012-07-27 13:35:41

回答

0

它通常是一個好主意,有定義的命名空間和目標名稱,但作爲彼得魯杜米特Gardea指出,這不是絕對必要的。下面是一個絕對的作品組合:

AccountList.xsd

<xs:schema 
    version="1.0" 
    elementFormDefault="qualified" 
    attributeFormDefault="unqualified" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:tns="http://www.myorg.com/xsd/accList" 
    targetNamespace="http://www.myorg.com/xsd/accList" 
    xmlns:common="http://www.myorg.com/xsd/gen_fin"> 

    <xs:import namespace="http://www.myorg.com/xsd/gen_fin" schemaLocation="common.xsd" /> 

    <xs:element name="fundamo"> 
     <xs:complexType> 
      <xs:sequence> 
       <xs:element name="response" type="common:response" 
        minOccurs="1" maxOccurs="1" /> 
       <xs:element name="transaction" type="tns:transaction" 
        minOccurs="0" maxOccurs="1" /> 
      </xs:sequence> 
     </xs:complexType> 
    </xs:element> 

    <xs:complexType name="transaction"> 
     <xs:sequence> 
      <xs:element name="transactionRef" type="xs:string" /> 
      <xs:element name="dateTime" type="xs:string" /> 
      <xs:element name="userName" type="xs:string" /> 
     </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

common.xsd

<xs:schema 
    version="1.0" 
    elementFormDefault="qualified" 
    attributeFormDefault="unqualified" 
    xmlns="http://www.myorg.com/xsd/gen_fin" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.myorg.com/xsd/gen_fin"> 

    <xs:complexType name="response"> 
     <xs:sequence> 
      <xs:element name="code" type="xs:string" /> 
      <xs:element name="description" type="xs:string" /> 
     </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

NewFile.xml(基於該架構):

<tns:fundamo xmlns:p="http://www.myorg.com/xsd/gen_fin" 
    xmlns:tns="http://www.myorg.com/xsd/accList" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.myorg.com/xsd/accList AccountList.xsd "> 
    <tns:response> 
     <p:code>p:code</p:code> 
     <p:description>p:description</p:description> 
    </tns:response> 
</tns:fundamo> 

ValidateXml。 java:

import java.io.File; 
import java.io.IOException; 

import javax.xml.XMLConstants; 
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 
import javax.xml.transform.dom.DOMSource; 
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 ValidateXml { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
     try { 
      DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); 
      documentBuilderFactory.setNamespaceAware(true); 
      DocumentBuilder parser = documentBuilderFactory.newDocumentBuilder(); 
      Document document = parser.parse(new File("NewFile.xml")); 

      Schema schema = schemaFactory.newSchema(new File("AccountList.xsd")); 
      Validator validator = schema.newValidator(); 

      validator.validate(new DOMSource(document)); 
     } catch (SAXException e) { 
      e.printStackTrace(); 
     } catch (ParserConfigurationException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    } 

} 

與「無法找到元素聲明」有關的錯誤通常與XML文檔不能識別名稱空間有關。驗證您的兩個XSD路徑是否正確,並返回到您構建可識別名稱空間的XML文檔的代碼塊。

+2

錯誤答案(虛擬-1)。從XSD的角度來看,不,你不需要目標命名空間。假設導入位置正確解析,發佈的XSD完全有效。 – 2012-07-27 14:42:20

+0

正在接收:org.xml.sax.SAXParseException; lineNumber:1; columnNumber:48; cvc-elt.1:找不到元素'fundamo'的聲明。 – user243773 2012-07-27 14:47:56