none
Why doesn't my code that uses System.Xml.XmlReader detect an invalid XML file? RRS feed

  • Question

  • Goal

    Using PowerShell 5.1, detect an invalid XML file by validating it against an XML schema using Microsoft's System.Xml.XmlReader. I'll detect the invalid XML file by catching the XMLException that XmlReader throws on an XML parse error.

    Note: I don't want to use PowerShell Community Extensions Test-Xml cmdlet.

    The problem

    The line of code $readerResult = $xmlReader.Read() does not throw the XMLException I expect when parsing an invalid XML file

    My XSD

    <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    targetNamespace="urn:config-file-schema">
      <xs:element name="notes">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="note" maxOccurs="unbounded" minOccurs="0">
              <xs:complexType>
                <xs:sequence>
                  <xs:element type="xs:string" name="to"/>
                  <xs:element name="from">
                    <xs:complexType>
                      <xs:simpleContent>
                        <xs:extension base="xs:string">
                          <xs:attribute type="xs:byte" name="type" use="optional"/>
                        </xs:extension>
                      </xs:simpleContent>
                    </xs:complexType>
                  </xs:element>
                  <xs:element type="xs:string" name="heading"/>
                  <xs:element type="xs:string" name="body"/>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>

    My invalid XML (second line uses bogus element name notXXXes)

    <?xml version="1.0" encoding="UTF-8"?>
    <notXXXes xmlns="urn:config-file-schema">
        <note>
            <to>Tove</to>
            <from type="1">Jani</from>
            <heading>Reminder</heading>
            <body>Don't forget me this weekend!</body>
        </note>
        <note>
            <to>Bob</to>
            <from type="2">KeyW</from>
            <heading>Reminder</heading>
            <body>I won't</body>
        </note>
    </notes>

    My code

    When run, $readerResult returns true, indicating that the next node was read successfully. I expect $xmlReader.Read() to throw an XMLException because the XML file content violates the schema.

    cls
    $error.clear()
    
    try
    {
    
        [System.Xml.Schema.XmlSchemaSet] $schemaSet = New-Object -TypeName System.Xml.Schema.XmlSchemaSet
        $schemaSet.Add("urn:config-file-schema","C:\Users\x\Desktop\test.xsd");
    
        [System.Xml.XmlReaderSettings] $readerSettings = New-Object -TypeName System.Xml.XmlReaderSettings
        $readerSettings.Schemas = $schemaSet
        $readerSettings.ValidationType = [System.Xml.ValidationType]::Schema
        $readerSettings.ConformanceLevel = [System.Xml.ConformanceLevel]::Fragment
        $readerSettings.IgnoreWhitespace = $true;
        $readerSettings.IgnoreComments = $true;
    
        [System.Xml.XmlReader]$xmlReader = [System.Xml.XmlReader]::Create("C:\Users\x\Desktop\test.xml", $readerSettings)
    
        #just to show that Schemas was set up OK
        "target namespace: " + $readerSettings.Schemas.Schemas().TargetNamespace
    
        $readerResult = $xmlReader.Read()
    
        "readerResult: " + $readerResult
    }
    catch
    {
        "error: " + $error
    }
    finally
    {
        $xmlReader.Close()
    }

    • Edited by Nova Sys Eng Saturday, September 8, 2018 2:36 PM
    • Moved by Bill_Stewart Wednesday, December 12, 2018 9:35 PM Unanswerable drive-by question
    Saturday, September 8, 2018 2:32 PM

All replies

  • You XML is incomplete in its entirety.  The root element is not closed.


    \_(ツ)_/

    Saturday, September 8, 2018 5:57 PM
  • You are reading one element.  The element you have just read is here:

    $xmlReader.Value

    The first element is the xml declaration line: "version="1.0" encoding="UTF-8""

    Performa a second read and you will get an error.


    \_(ツ)_/

    Saturday, September 8, 2018 11:41 PM
  • Here is the easy way to validate nodes in an XML document against a schema.

    [xml]$xml = Get-Content 'd:\scripts\test.xml'
    $xml.Schemas.Add('urn:config-file-schema','d:\scripts\test.xsd')
    $xml.Schemas.Compile()
    $xml.Validate($null,$xml.DocumentElement)


    \_(ツ)_/


    • Edited by jrv Sunday, September 9, 2018 12:04 AM
    Sunday, September 9, 2018 12:00 AM