XML反序列化问题

时间:2018-03-12 09:25:51

标签: c# xml xsd xml-deserialization

我有一些严重的问题反序列化xml文档。我不负责结构,因此根本不能进行任何修改(仅在运行时删除/替换一些静态内容)。

该文档包含一些具有模块深度的查询构建器的条件。

首先,这是一个可以由外部应用程序生成的示例XML文件。它的结构取决于条件的复杂程度。

这是一个简单的例子:

XML简单

<?xml version="1.0"?>
<QueryBuilderSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://dev.somecompany.com/settings/web/querybuilder">
  <Root>
    <Operation>And</Operation>
    <Conditions xsi:type="Condition">
      <DBName>BELEG_NR_</DBName>
      <Provider xsi:type="TextConditionProvider">
        <Operation>Contains</Operation>
        <Value>LC</Value>
        <SystemFunction>None</SystemFunction>
      </Provider>
    </Conditions>
  </Root>
</QueryBuilderSettings>

这是一个复杂的问题:

XML complex

<?xml version="1.0"?>
<QueryBuilderSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://dev.somecompany.com/settings/web/querybuilder">
  <Root>
    <Operation>And</Operation>
    <Conditions xsi:type="Condition">
      <DBName>INVOICEID</DBName>
      <Provider xsi:type="TextConditionProvider">
        <Operation>Contains</Operation>
        <Value>LC</Value>
        <SystemFunction>None</SystemFunction>
      </Provider>
    </Conditions>
    <Conditions xsi:type="Condition">
      <DBName>DEPARTMENT</DBName>
      <Provider xsi:type="TextConditionProvider">
        <Operation>Equal</Operation>
        <Value>Lager</Value>
        <SystemFunction>None</SystemFunction>
      </Provider>
    </Conditions>
    <Conditions xsi:type="GroupCondition">
      <Operation>Or</Operation>
      <Conditions xsi:type="Condition">
        <DBName>STATEFIELD_1</DBName>
        <Provider xsi:type="TextConditionProvider">
          <Operation>NotEqual</Operation>
          <Value>TEST</Value>
          <SystemFunction>None</SystemFunction>
        </Provider>
      </Conditions>
      <Conditions xsi:type="Condition">
        <DBName>STATEFIELD_2</DBName>
        <Provider xsi:type="EmptyConditionProvider">
          <Operation>Empty</Operation>
        </Provider>
      </Conditions>
      <Conditions xsi:type="GroupCondition">
        <Operation>Or</Operation>
        <Conditions xsi:type="Condition">
          <DBName>DEPARTMENT</DBName>
          <Provider xsi:type="EmptyConditionProvider">
            <Operation>NotEmpty</Operation>
          </Provider>
        </Conditions>
        <Conditions xsi:type="Condition">
          <DBName>INVOICEDATE</DBName>
          <Provider xsi:type="DateConditionProvider">
            <Operation>Equal</Operation>
            <Value>2018-03-01T00:00:00Z</Value>
            <SystemFunction>None</SystemFunction>
          </Provider>
        </Conditions>
        <Conditions xsi:type="GroupCondition">
          <Operation>Or</Operation>
          <Conditions xsi:type="Condition">
            <DBName>INVOICEDATE</DBName>
            <Provider xsi:type="DateConditionProvider">
              <Operation>NotEqual</Operation>
              <Value>2018-03-02T00:00:00Z</Value>
              <SystemFunction>None</SystemFunction>
            </Provider>
          </Conditions>
          <Conditions xsi:type="Condition">
            <DBName>CUSTOMERID</DBName>
            <Provider xsi:type="RangeNumericConditionProvider">
              <Operation>Range</Operation>
              <FromValue>0</FromValue>
              <ToValue>12000</ToValue>
            </Provider>
          </Conditions>
        </Conditions>
      </Conditions>
    </Conditions>
  </Root>
</QueryBuilderSettings>

XSD生成以下输出(复杂的):

XSD

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="QueryBuilderSettings" targetNamespace="http://dev.somecompany.com/settings/web/querybuilder" xmlns:mstns="http://dev.somecompany.com/settings/web/querybuilder" xmlns="http://dev.somecompany.com/settings/web/querybuilder" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" attributeFormDefault="qualified" elementFormDefault="qualified">
  <xs:element name="Conditions">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Operation" type="xs:string" minOccurs="0" />
        <xs:element name="DBName" type="xs:string" minOccurs="0" />
        <xs:element name="Provider" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Operation" type="xs:string" minOccurs="0" />
              <xs:element name="FromValue" type="xs:string" minOccurs="0" />
              <xs:element name="ToValue" type="xs:string" minOccurs="0" />
              <xs:element name="Value" type="xs:string" minOccurs="0" />
              <xs:element name="Period" type="xs:string" minOccurs="0" />
              <xs:element name="SystemFunction" type="xs:string" minOccurs="0" />
              <xs:element name="AddWildcard" type="xs:string" minOccurs="0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element ref="Conditions" minOccurs="0" maxOccurs="unbounded" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="QueryBuilderSettings" msdata:IsDataSet="true" msdata:Locale="en-US">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="Conditions" />
        <xs:element name="Root">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Operation" type="xs:string" minOccurs="0" />
              <xs:element ref="Conditions" minOccurs="0" maxOccurs="unbounded" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

这是为xsd-file

生成的cs-class

MODEL

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class Conditions {

    private string operationField;

    private string dBNameField;

    private ConditionsProvider[] providerField;

    private Conditions[] conditions1Field;

    /// <remarks/>
    public string Operation {
        get {
            return this.operationField;
        }
        set {
            this.operationField = value;
        }
    }

    /// <remarks/>
    public string DBName {
        get {
            return this.dBNameField;
        }
        set {
            this.dBNameField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Provider")]
    public ConditionsProvider[] Provider {
        get {
            return this.providerField;
        }
        set {
            this.providerField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Conditions")]
    public Conditions[] Conditions1 {
        get {
            return this.conditions1Field;
        }
        set {
            this.conditions1Field = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class ConditionsProvider {

    private string operationField;

    private string fromValueField;

    private string toValueField;

    private string valueField;

    private string periodField;

    private string systemFunctionField;

    private string addWildcardField;

    /// <remarks/>
    public string Operation {
        get {
            return this.operationField;
        }
        set {
            this.operationField = value;
        }
    }

    /// <remarks/>
    public string FromValue {
        get {
            return this.fromValueField;
        }
        set {
            this.fromValueField = value;
        }
    }

    /// <remarks/>
    public string ToValue {
        get {
            return this.toValueField;
        }
        set {
            this.toValueField = value;
        }
    }

    /// <remarks/>
    public string Value {
        get {
            return this.valueField;
        }
        set {
            this.valueField = value;
        }
    }

    /// <remarks/>
    public string Period {
        get {
            return this.periodField;
        }
        set {
            this.periodField = value;
        }
    }

    /// <remarks/>
    public string SystemFunction {
        get {
            return this.systemFunctionField;
        }
        set {
            this.systemFunctionField = value;
        }
    }

    /// <remarks/>
    public string AddWildcard {
        get {
            return this.addWildcardField;
        }
        set {
            this.addWildcardField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace="", IsNullable=false)]
public partial class QueryBuilderSettings {

    private object[] itemsField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Conditions", typeof(Conditions))]
    [System.Xml.Serialization.XmlElementAttribute("Root", typeof(QueryBuilderSettingsRoot))]
    public object[] Items {
        get {
            return this.itemsField;
        }
        set {
            this.itemsField = value;
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true)]
public partial class QueryBuilderSettingsRoot {

    private string operationField;

    private Conditions[] conditionsField;

    /// <remarks/>
    public string Operation {
        get {
            return this.operationField;
        }
        set {
            this.operationField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Conditions")]
    public Conditions[] Conditions {
        get {
            return this.conditionsField;
        }
        set {
            this.conditionsField = value;
        }
    }
}

到目前为止,这里没有问题。

所以基本上我将它反序列化为:

var qbs = prlm.ExtendedStatement?.Replace(@" xmlns=""http://dev.somecompany.com/settings/web/querybuilder""", ""); // replace because of error, see post below

var deserializer = new XmlSerializer(typeof(QueryBuilderSettings));
var xmlDoc = new XmlDocument();

if (string.IsNullOrEmpty(qbs)) return null;
xmlDoc.LoadXml(qbs);

using (XmlReader reader = new XmlNodeReader(xmlDoc))
{
    var obj = (QueryBuilderSettings)deserializer.Deserialize(reader); // EXCEPTION occurs here

    ...
}

如果我尝试反序列化原始的xml文件,我会收到以下错误:

<QueryBuilderSettings xmlns='http://dev.somecompany.com/settings/web/querybuilder'> was not expected

好的,没问题。我只是在运行时删除它。现在我收到以下错误:

The same table 'Conditions' cannot be the child table in two nested relations.

妈的,但是我看到这里发生了什么。所以我认为这将是一个很好的&#39;想要从

更改xsd文件
msdata:IsDataSet="true"

msdata:IsDataSet="false"

会导致以下错误:

The specified type was not recognized: Name='Condition', Namespace='', at <Conditions xmlns=''>

我从来没有这样的问题,幸运的是,所以我不知道如何解决这个问题,生成一个类模型,我可以在运行时轻松使用(如果可能的话,我会避免使用数据集/表) )。

希望你们中的任何人都可以帮助我并指出正确的方向,因为我现在没有想法。

提前致谢。

0 个答案:

没有答案