XDocument.Validate проблемы пространства имен
Я изменил пример MSDN, чтобы отразить мою проблему.
При использовании пространства имен я не могу получить документ для проверки, как я ожидал, и при проверке документа, который не имеет пространства имен, он проверяется независимо от того, есть ли в нем ошибка или нет.
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
Элемент "Root" в пространстве имен "http://somenamespace.com" имеет недопустимый дочерний элемент "Child1" в пространстве имен "http://somenamespace.com". Список возможных ожидаемых элементов: "Child1".
doc1 не подтвердил
Подтверждение doc2
doc2 подтвержден
1 ответ
Ну вам нужно будет добавить elementFormDefault="qualified"
к вашей схеме (на xsd:schema
элемент), если вы хотите, чтобы ваш doc1
где вы поместите пространство имен на каждый элемент, чтобы быть действительным. С вашей текущей схемой действительным экземпляром будет тот, где Root
находится в targetNamespace, но ChildX
элементы не находятся в пространстве имен.
Вторая проблема - это известная проблема с проверкой схемы и пространством имен. Проверяющий анализатор ищет подходящую схему для корневого элемента, если ее нет, она выполняет слабую проверку, поэтому вы не получите ошибку проверки. С помощью API XmlReader вы можете запросить предупреждение в этом случае, но я не знаю, как это сделать с помощью метода 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