Frage

Hier ist mein erster Versuch XML Validierung mit XSD.

Die XML-Datei validiert werden:

<?xml version="1.0" encoding="utf-8" ?>
<config xmlns="Schemas" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="config.xsd">
  <levelVariant>
    <filePath>SampleVariant</filePath>
  </levelVariant>
  <levelVariant>
    <filePath>LegendaryMode</filePath>
  </levelVariant>
  <levelVariant>
    <filePath>AmazingMode</filePath>
  </levelVariant>
</config>

Die XSD, befindet sich in "Schemen / config.xsd" in Bezug auf die XML-Datei validiert werden:

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="config">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="levelVariant">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="filePath" type="xs:anyURI">
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Im Moment möchte ich nur die XML-Datei zu validieren, genau wie es derzeit scheint. Sobald ich dies besser zu verstehen, werde ich mehr erweitern. Muss ich so viele Zeilen für etwas so Einfaches wie die XML-Datei wirklich, wie es existiert zur Zeit?

Der Validierungscode in C #:

        public void SetURI(string uri)
        {
            XElement toValidate = XElement.Load(Path.Combine(PATH_TO_DATA_DIR, uri) + ".xml");

// begin confusion

       // exception here
       string schemaURI = toValidate.Attributes("xmlns").First().ToString() 
                              + toValidate.Attributes("xsi:noNamespaceSchemaLocation").First().ToString();
        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add(null, schemaURI);

        XDocument toValidateDoc = new XDocument(toValidate);
        toValidateDoc.Validate(schemas, null);
// end confusion

            root = toValidate;
        }

Sie den obigen Code Lauf gibt diese Ausnahme:

The ':' character, hexadecimal value 0x3A, cannot be included in a name.

Jede Beleuchtung würde geschätzt.

War es hilfreich?

Lösung

Anstatt die XDocument.Validate Erweiterungsmethode, würde ich eine XmlReader , die so konfiguriert werden kann, ein Inline-Schema über XmlReaderSettings . Sie könnten einige etwas wie den folgenden Code tun.

public void VerifyXmlFile(string path)
{
    // configure the xmlreader validation to use inline schema.
    XmlReaderSettings config = new XmlReaderSettings();
    config.ValidationType = ValidationType.Schema;
    config.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
    config.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
    config.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
    config.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

    // Get the XmlReader object with the configured settings.
    XmlReader reader = XmlReader.Create(path, config);

    // Parsing the file will cause the validation to occur.
    while (reader.Read()) ;

}

private void ValidationCallBack(object sender, ValidationEventArgs vea)
{
    if (vea.Severity == XmlSeverityType.Warning)
        Console.WriteLine(
            "\tWarning: Matching schema not found.  No validation occurred. {0}",
            vea.Message);
    else
        Console.WriteLine("\tValidation error: {0}", vea.Message);

}

Der obige Code übernimmt die folgenden Anweisungen.

using System.Xml;
using System.Xml.Schema;

Sie einfach diese einfach zu halten ich keine boolean oder eine Sammlung von Validierungsfehler zurückgekommen, könnte man leicht diese ändern, dies zu tun.

Hinweis: Ich änderte Ihre config.xml und config.xsd sie zu validieren zu bekommen. Dies sind die Änderungen, die ich gemacht.

config.xsd:

<xs:element maxOccurs="unbounded" name="levelVariant">

config.xml:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="config.xsd">

Andere Tipps

Im Anschluss ist aus einer Arbeitsprobe:

Verwendung:

XMLValidator val = new XMLValidator();
if (!val.IsValidXml(File.ReadAllText(@"d:\Test2.xml"), @"D:\Test2.xsd"))
   MessageBox.Show(val.Errors);

Klasse:

public class CXmlValidator
{
    private int nErrors = 0;
    private string strErrorMsg = string.Empty;
    public string Errors { get { return strErrorMsg; } }
    public void ValidationHandler(object sender, ValidationEventArgs args)
    {
        nErrors++;
        strErrorMsg = strErrorMsg + args.Message + "\r\n";
    }

    public bool IsValidXml(string strXml/*xml in text*/, string strXsdLocation /*Xsd location*/)
    {
        bool bStatus = false;
        try
        {
            // Declare local objects
            XmlTextReader xtrReader = new XmlTextReader(strXsdLocation);
            XmlSchemaCollection xcSchemaCollection = new XmlSchemaCollection();
            xcSchemaCollection.Add(null/*add your namespace string*/, xtrReader);//Add multiple schemas if you want.

            XmlValidatingReader vrValidator = new XmlValidatingReader(strXml, XmlNodeType.Document, null);
            vrValidator.Schemas.Add(xcSchemaCollection);

            // Add validation event handler
            vrValidator.ValidationType = ValidationType.Schema;
            vrValidator.ValidationEventHandler += new ValidationEventHandler(ValidationHandler);

            //Actual validation, read conforming the schema.
            while (vrValidator.Read()) ;

            vrValidator.Close();//Cleanup

            //Exception if error.
            if (nErrors > 0) { throw new Exception(strErrorMsg); }
            else { bStatus = true; }//Success
        }
        catch (Exception error) { bStatus = false; }

        return bStatus;
    }
}

Der obige Code validiert folgende xml (code3) gegen XSD (code4).

<!--CODE 3 - TEST1.XML-->
<address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test1.xsd"> 
<name>My Name</name>
<street>1, My Street Address</street>
<city>Far</city>
<country>Mali</country>
</address>

<!--CODE 4 - TEST1.XSD-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="address">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="street" type="xs:string"/>
<xs:element name="city" type="xs:string"/>
<xs:element name="country" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

Bei der Validierung gegen Ihre xml / xsd ich von Fehlern erhalten anders als Ihr; Ich denke, das kann Ihnen helfen, (Hinzufügen / Entfernen XML-Elemente) weiterhin von hier:

Fehler

Sie können auch den umgekehrten Prozess versuchen; versuchen, das Schema von Ihrem xml und vergleichen Sie mit Ihrem tatsächlichen xsd Erzeugung - sehen Sie den Unterschied; und der einfachste Weg, dies zu tun ist, generieren zu verwenden Schema VS IDE. Es folgt, wie würden Sie das tun:

Hope, das hilft.

- EDIT -

Dies ist auf Johns Wunsch, bitte aktualisierten Code unter Verwendung von nicht veralteten Methoden finden Sie unter:

public bool IsValidXmlEx(string strXmlLocation, string strXsdLocation)
{
    bool bStatus = false;
    try
    {
        // Declare local objects
        XmlReaderSettings rs = new XmlReaderSettings();
        rs.ValidationType = ValidationType.Schema;
        rs.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation | XmlSchemaValidationFlags.ReportValidationWarnings;
        rs.ValidationEventHandler += new ValidationEventHandler(rs_ValidationEventHandler);
        rs.Schemas.Add(null, XmlReader.Create(strXsdLocation));

        using (XmlReader xmlValidatingReader = XmlReader.Create(strXmlLocation, rs))
        { while (xmlValidatingReader.Read()) { } }

        ////Exception if error.
        if (nErrors > 0) { throw new Exception(strErrorMsg); }
        else { bStatus = true; }//Success
    }
    catch (Exception error) { bStatus = false; }

    return bStatus;
}

void rs_ValidationEventHandler(object sender, ValidationEventArgs e)
{
    if (e.Severity == XmlSeverityType.Warning) strErrorMsg += "WARNING: " + Environment.NewLine;
    else strErrorMsg += "ERROR: " + Environment.NewLine;
    nErrors++;
    strErrorMsg = strErrorMsg + e.Exception.Message + "\r\n";
}

Verwendung:

if (!val.IsValidXmlEx(@"d:\Test2.xml", @"D:\Test2.xsd"))
                MessageBox.Show(val.Errors);
            else
                MessageBox.Show("Success");

test2.xml

<?xml version="1.0" encoding="utf-8" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test2.xsd">
  <levelVariant>
    <filePath>SampleVariant</filePath>
  </levelVariant>
  <levelVariant>
    <filePath>LegendaryMode</filePath>
  </levelVariant>
  <levelVariant>
    <filePath>AmazingMode</filePath>
  </levelVariant>
</config>

Test2.XSD (generiert aus VS IDE)

<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="config">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="levelVariant">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="filePath" type="xs:anyURI">
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Dies ist garantiert an die Arbeit!

Ihr Code das Schema Lage zu extrahieren sieht seltsam. Warum bekommen Sie den Wert des Attributs xmlns und verketten es mit dem Wert des xsi: noNamespaceSchemaLocation Attribut? Die Ausnahme wird durch die Tatsache, dass Sie nicht ein Präfix in einem Aufruf Attribute angeben können; Sie müssen die gewünschten XNamespace angeben.

Versuchen Sie, diese (nicht getestet):

// Load document
XDocument doc = XDocument.Load("file.xml");

// Extract value of xsi:noNamespaceSchemaLocation
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
string schemaURI = (string)doc.Root.Attribute(xsi + "noNamespaceSchemaLocation");

// Create schema set
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("Schemas", schemaURI);

// Validate
doc.Validate(schemas, (o, e) =>
                      {
                          Console.WriteLine("{0}", e.Message);
                      });
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top