XDocument.Validate 命名空间问题

发布于 2024-12-28 03:06:17 字数 2495 浏览 0 评论 0原文

我已修改 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

命名空间“http://somenamespace.com”中的元素“Root”在命名空间“http://somenamespace.com”中具有无效的子元素“Child1”。预期可能元素的列表:“Child1”。

doc1 未验证 正在

验证 doc2

doc2 已验证

I have modified the MSDN example to reflect my problem.

When using a namespace I can't get the document to validate as I would expect and when validating a document that doesnt have a namespace it validates regardless of whether or not it has an error in it or not.

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

Output:

Validating doc1

The element 'Root' in namespace 'http://somenamespace.com' has invalid child element 'Child1' in namespace 'http://somenamespace.com'. List of possible elements expected: 'Child1'.

doc1 did not validate

Validating doc2

doc2 validated

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

み格子的夏天 2025-01-04 03:06:17

那么,如果您希望 doc1 位于您的架构中(在 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

Well you will need to add elementFormDefault="qualified" to your schema (on the xsd:schema element) if you want your doc1 where you put the namespace on each element to be valid. With your current schema a valid instance would be one where the Root is in the targetNamespace but the ChildX elements are in no namespace.

The second issue is a known problem with schema validation and namespaces, the validating parser looks for a matching schema for the root element, if there is none that it does lax validation so you don't get a validation error. With the XmlReader API you can ask for warning to be emitted in that case but I don't know how to do that with the Validate method. So you would need code like

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文