2011-09-21 62 views
5

我正在使用嵌套XSD模式来验证XML文档。导入的XSD使用自己的目标命名空间,我可以使用Liquid XML Studio验证下面给出的示例XML。但是,当我使用下面的C#代码运行验证时,它会因类型声明错误而失败(请参见下文)。我花了很多时间试图找出,但没有运气:使用嵌套XSD模式的XML验证错误 - 类型未声明

主要XSD架构(DataItem.xsd):

<?xml version="1.0" encoding="utf-8" ?> 
<xs:schema xmlns:DataNumeric="Doc.DataNumeric" xmlns:DataYesNo="Doc.DataYesNo" attributeFormDefault="qualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:import schemaLocation="DataNumeric.xsd" namespace="Doc.DataNumeric" /> 
    <xs:import schemaLocation="DataYesNo.xsd" namespace="Doc.DataYesNo" /> 
    <xs:complexType name="tDataItem"> 
     <xs:choice> 
     <xs:element name="DataNumeric" type="DataNumeric:tDataNumeric" /> 
     <xs:element name="DataYesNo" type="DataYesNo:tDataYesNo" /> 
     </xs:choice> 
    </xs:complexType> 
    <xs:element name="DataItem" type="tDataItem" /> 
</xs:schema> 

包括XSD架构(DataNumeric.xsd):

**<?xml version="1.0" encoding="utf-8" ?> 
<xs:schema xmlns:DataNumeric="Doc.DataNumeric" elementFormDefault="qualified" targetNamespace="Doc.DataNumeric" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:complexType name="tDataNumeric"> 
    <xs:sequence> 
     <xs:element name="Answer" type="xs:double" /> 
    </xs:sequence> 
    </xs:complexType> 
    <xs:element name="DataNumeric" type="DataNumeric:tDataNumeric" /> 
</xs:schema>** 

的XML:

<DataItem> 
    <DataNumeric xmlns:DataNumeric="Doc.DataNumeric"> 
    <DataNumeric:Answer>37.8</DataNumeric:Answer> 
    </DataNumeric> 
</DataItem> 

验证错误:

XmlSchemaValidationException:类型 'Doc.DataNumeric:tDataNumeric' 未声明。

C#验证码:

XDocument xDoc = XDocument.Parse(xxxxxxx); 
string xsdPath = ConfigUtils.GetXsdPath(XsdSchemaIdentifier.HHDataItem); 
FileStream fs = new FileStream(xsdPath, FileMode.Open); 
XmlReader reader = XmlReader.Create(fs); 
XmlSchemaSet xss = new XmlSchemaSet(); 
xss.Add("", reader); 
fs.Close(); 
fs.Dispose(); 

xDoc.Validate(xss, null); 

回答

5

我发现了一个令人沮丧的一天后,问题和迭代的一半。更改:

FileStream fs = new FileStream(xsdPath, FileMode.Open); 
XmlReader reader = XmlReader.Create(fs); 
XmlSchemaSet xss = new XmlSchemaSet(); 
xss.Add("", reader); 

XmlSchemaSet xss = new XmlSchemaSet(); 
xss.Add("", xsdPath); 

解决了这个问题。但是我仍在寻找为什么的答案?这两种方法都是向架构集添加模式的有效方式(即2次重载)。

+5

失败的原因是您的XSD导入了其他XSD。当你使用'XmlReader'时,它不知道底层'Stream'输入的位置是什么,所以它没有办法找到导入。当您将模式文件的路径提供给'XmlSchemaSet'时,它可以根据该路径执行自己的定位工作。 – arootbeer

1

arootbeer是正确的关于如何您的xsd导入另一个xsd。然而,另一种解决方案是首先将导入的xsd添加到XmlSchemaSet中,然后添加执行实际导入的xsd。

//Xsd file that is being imported 
FileStream importedXsdStream = new FileStream(importedXsdPath, FileMode.Open); 
XmlReader xmlReader = XmlReader.Create(importedXsdStream); 
XmlSchemaSet xmlSchemaSet = new XmlSchemaSet(); 
xmlSchemaSet.Add("NameSpace.SomeNameSpace", xmlReader); 

//Your code 
FileStream fs = new FileStream(xsdPath, FileMode.Open); 
XmlReader reader = XmlReader.Create(fs); 
XmlSchemaSet xss = new XmlSchemaSet(); 
xss.Add("", reader); 

通知我把命名空间作为第一个参数添加导入XSD到XmlSchemaSet中时。这可能是必要的,具体取决于目标名称空间是否存在与导入的xsd中提供的名称空间不匹配的错误。