C # XmlDocument проверяет различные узлы с разными схемами - PullRequest
0 голосов
/ 19 октября 2018

У меня есть вопрос о проверке XML с использованием класса XmlDocument, особенно это метод .Validate().Сценарий выглядит следующим образом: у меня есть XML, который выглядит следующим образом:

<root>
   <Message id="1234">
      <Content1>
         <randomTag1>data</randomTag1>
         <randomTag2>data</randomTag2>
      </Content>
   </Message>
<root>

и следующие две схемы .xsd

1:

<xs:schema id="root"  xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element name="root" type="rType"/>
 <xs:complexType name="ThreeDSecure">
  <xs:sequence>
   <xs:element name="Message" type="Message"/>
  </xs:sequence>
 </xs:complexType>

<xs:complexType name="Message">
 <xs:choice maxOccurs="1">
  <xs:element name="Content1"/>
  <xs:element name="Content2"/>
 </xs:choice>
 <xs:attribute name="id" type="xs:string" use="required"/>
</xs:complexType>

2:

<xs:schema id="Content1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element name="Content1" type="c1Type"/>
  <xs:complexType name="c1Type">
   <xs:sequence>
     <xs:element name="randomTag1"/>
     <xs:element name="randomTag2"/>
   </xs:sequence>
  </xs:complexType>
</xs:schema>

Цель состоит в том, чтобы иметь возможность загрузить XmlDocument и добавить к нему два XmlSchemaSet, а затем иметь возможность проверить весь документ с первым .xsd, а затемесли проверка не содержит ошибок для проверки узла <Content1> со вторым .xsd

Я использую следующий код:

public bool Parse(string xmlString)
    {
        var doc = new XmlDocument();

        try { doc.LoadXml(xmlString); }
        catch (Exception ex)
        {
            return false;
        }

        var errors = new List<string>();

        doc.Schemas.Add(/*load the first schema*/);
        doc.Validate((o, e) =>
                            {
                                if (e.Severity == XmlSeverityType.Error)
                                    errors.Add(e.Message);
                            });
        if(errors.Count > 0)
        {
            return false;
        }

        var msgNode = doc.SelectSingleNode("//Message");

        var realMsg = msgNode.FirstChild;
        //we do this because we do not know if this node is "Content1" or "Content2" because for "Content2" there is a different .xsd schema
        doc.Schemas.Add(/*load the second schema using the realMsg.Name*/);

        errors.Clear();
        doc.Validate((o,e) => 
                            {
                                if(e.Severity == XmlSeverityType.Error)
                                    errors.Add(e.Message);
                            });
        if (errors.Count > 0)
        {

            return false;
        }

        return true;
    }

Код работает нормально, нокогда я намеренно отправляю неверный формат XML для тега <Content1>, вторая проверка не выдает никаких ошибок.

Должно быть, я что-то не так делаю, но не могу понять, что это.Или, может быть, я подхожу к проблеме другим (не известным мне) подходом?

------- РЕДАКТИРОВАТЬ --------

Я пробовалте же схемы xsd, но я загружаю их в другом XmlDocument, и он отлично работает:

public bool Parse(string xmlString)
    {
        var doc = new XmlDocument();

        try { doc.LoadXml(xmlString); }
        catch (Exception ex)
        {
            return false;
        }

        var errors = new List<string>();

        doc.Schemas.Add(/*load the first schema*/);
        doc.Validate((o, e) =>
                            {
                                if (e.Severity == XmlSeverityType.Error)
                                    errors.Add(e.Message);
                            });
        if(errors.Count > 0)
        {
            return false;
        }

        var msgNode = doc.SelectSingleNode("//Message");

        var realMsg = msgNode.FirstChild;
        var realDoc = new XmlDocument();
        realDoc.LoadXml(realMsg.OuterXml);
        //we do this because we do not know if this node is "Content1" or "Content2" because for "Content2" there is a different .xsd schema
        realDoc.Schemas.Add(/*load the second schema using the realMsg.Name*/);

        errors.Clear();
        realDoc.Validate((o,e) => 
                            {
                                if(e.Severity == XmlSeverityType.Error)
                                    errors.Add(e.Message);
                            });
        if (errors.Count > 0)
        {

            return false;
        }

        return true;
    }

Есть ли способ избежать новых XmlDocument?

С уважениемЮлианский

...