2012-07-27 125 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