C#XmlDocument使用不同的架构验证不同的节点

时间:2018-10-19 08:00:24

标签: c# xml xsd xml-parsing

我有一个关于使用XmlDocument类进行XML验证的问题,尤其是它的.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验证整个文档,然后验证没有错误,可以使用第二个.xsd

验证<Content1>节点

我正在使用的代码是这样的:

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;
    }

代码运行良好,但是当我有意为<Content1>标签发送错误的XML格式时,第二次验证不会产生任何错误。

这一定是我做错了,但是我找不到它是什么。 或者,也许我会以另一种(我不知道的)方法来解决问题?

-------编辑--------

我尝试了相同的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

关于, 朱利安

0 个答案:

没有答案