2012-01-20 4 views
3

나는이 문제를 반영하기 위해 MSDN 예제를 수정했다.XDocument.Validate 네임 스페이스 문제

네임 스페이스를 사용할 때 예상대로 문서를 가져올 수 없으며 네임 스페이스가없는 문서의 유효성을 검사 할 때 오류가 있는지 여부에 관계없이 유효성을 검사합니다.

Dim errors As Boolean = False 

Private Sub XSDErrors(ByVal o As Object, ByVal e As ValidationEventArgs) 
    Console.WriteLine("{0}", e.Message) 
    errors = True 
End Sub 

Private Function AddNameSpace(ByVal xDoc As XDocument, ByVal ns As XNamespace) As XDocument 
    For Each element As XElement In xDoc.Descendants 
     element.Name = ns + element.Name.LocalName 
    Next 
    Return xDoc 
End Function 

Sub Main() 
    Dim xsdMarkup As XElement = _ 
     <xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns="http://somenamespace.com" targetNamespace="http://somenamespace.com"> 
      <xsd:element name='Root'> 
       <xsd:complexType> 
        <xsd:sequence> 
         <xsd:element name='Child1' minOccurs='1' maxOccurs='1'/> 
         <xsd:element name='Child2' minOccurs='1' maxOccurs='1'/> 
        </xsd:sequence> 
       </xsd:complexType> 
      </xsd:element> 
     </xsd:schema> 
    Dim schemas As XmlSchemaSet = New XmlSchemaSet() 
    schemas.Add("http://somenamespace.com", xsdMarkup.CreateReader) 

    Dim doc1 As XDocument = _ 
     <?xml version='1.0'?> 
     <Root> 
      <Child1>content1</Child1> 
      <Child2>content1</Child2> 
     </Root> 

    Dim doc2 As XDocument = _ 
     <?xml version='1.0'?> 
     <Root> 
      <Child1>content1</Child1> 
      <Child3>content1</Child3> 
     </Root> 

    Dim ns As XNamespace = "http://somenamespace.com" 
    doc1 = AddNameSpace(doc1, ns) 

    Console.WriteLine("Validating doc1") 
    errors = False 
    doc1.Validate(schemas, AddressOf XSDErrors) 
    Console.WriteLine("doc1 {0}", IIf(errors = True, "did not validate", "validated")) 

    Console.WriteLine() 
    Console.WriteLine("Validating doc2") 
    errors = False 
    doc2.Validate(schemas, AddressOf XSDErrors) 
    Console.WriteLine("doc2 {0}", IIf(errors = True, "did not validate", "validated")) 

End Sub 

출력 :

검증 DOC1

요소 네임 스페이스에 '루트' 'http://somenamespace.com'에 잘못된 자식 요소 네임 스페이스에 '자식 1'에 http : // somenamespace .com '. 예상 가능한 요소 목록 : 'Child1'.

DOC1은 doc2에게 검증

를 확인하지 않았다

doc2 검증 당신이 네임 스페이스를 넣어 당신의 doc1을 원하는 경우

답변

5

는 잘 있습니다 (xsd:schema 요소에서) 스키마에 elementFormDefault="qualified"를 추가해야합니다 유효한 각 요소에 대해 현재 스키마에서 유효한 인스턴스는 Root이 targetNamespace에 있지만 ChildX 요소가 네임 스페이스에 있지 않은 인스턴스입니다.

두 번째 문제는 스키마 유효성 검사 및 네임 스페이스의 알려진 문제점입니다. 유효성 검사 구문 분석기는 유효하지 않은 유효성 검사를 수행하지 않으므로 유효성 검사 오류가 발생하지 않는 경우 루트 요소에 대해 일치하는 스키마를 찾습니다. 이 경우 XmlReader API를 사용하면 경고 메시지가 표시 될 수 있지만 Validate 메서드로이를 수행하는 방법을 알 수 없습니다. 따라서 코드가 필요합니다.

Imports System 
Imports System.Xml 
Imports System.Xml.Linq 
Imports System.Xml.Schema 

Module Module1 

    Dim errors As Boolean = False 

    Private Sub XSDErrors(ByVal o As Object, ByVal e As ValidationEventArgs) 
     Console.WriteLine("{0}", e.Message) 
     errors = True 
    End Sub 

    Private Function AddNameSpace(ByVal xDoc As XDocument, ByVal ns As XNamespace) As XDocument 
     For Each element As XElement In xDoc.Descendants 
      element.Name = ns + element.Name.LocalName 
     Next 
     Return xDoc 
    End Function 

    Sub Main() 
     Dim xsdMarkup As XElement = _ 
      <xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns="http://somenamespace.com" targetNamespace="http://somenamespace.com" elementFormDefault="qualified"> 
       <xsd:element name='Root'> 
        <xsd:complexType> 
         <xsd:sequence> 
          <xsd:element name='Child1' minOccurs='1' maxOccurs='1'/> 
          <xsd:element name='Child2' minOccurs='1' maxOccurs='1'/> 
         </xsd:sequence> 
        </xsd:complexType> 
       </xsd:element> 
      </xsd:schema> 
     Dim schemas As XmlSchemaSet = New XmlSchemaSet() 
     schemas.Add("http://somenamespace.com", xsdMarkup.CreateReader) 

     Dim doc1 As XDocument = _ 
      <?xml version='1.0'?> 
      <Root> 
       <Child1>content1</Child1> 
       <Child2>content1</Child2> 
      </Root> 

     Dim doc2 As XDocument = _ 
      <?xml version='1.0'?> 
      <Root> 
       <Child1>content1</Child1> 
       <Child3>content1</Child3> 
      </Root> 

     Dim ns As XNamespace = "http://somenamespace.com" 
     doc1 = AddNameSpace(doc1, ns) 

     Console.WriteLine("Validating doc1") 
     errors = False 
     doc1.Validate(schemas, AddressOf XSDErrors) 
     Console.WriteLine("doc1 {0}", IIf(errors = True, "did not validate", "validated")) 

     Console.WriteLine() 
     Console.WriteLine("Validating doc2") 
     Dim xrs As New XmlReaderSettings() 
     xrs.ValidationType = ValidationType.Schema 
     xrs.ValidationFlags = xrs.ValidationFlags Or XmlSchemaValidationFlags.ReportValidationWarnings 
     xrs.Schemas = schemas 
     AddHandler xrs.ValidationEventHandler, AddressOf XSDErrors 
     errors = False 
     Using xr1 As XmlReader = doc2.CreateReader() 
      Using xr2 As XmlReader = XmlReader.Create(xr1, xrs) 
       While xr2.Read() 

       End While 
      End Using 
     End Using 
     Console.WriteLine("doc2 {0}", IIf(errors = True, "did not validate", "validated")) 

    End Sub 

End Module