我如何为具有任意层次结构的类建模?

时间:2014-04-02 04:49:56

标签: c# .net

考虑以下XML:

<elements>
    <element attribute="value1">
        <or>
            <subelement attribute="value2" />
            <subelement attribute="value3" />
        </or>
    </element>
    <element attribute="value">
        <and>
            <subelement attribute="value4" />
            <subelement attribute="value5" />
            <or>
                <subelement attribute="value6" />
                <subelement attribute="value7" />
            </or>
        </and>
    </element>
</elements>

请注意,以下内容也有效:

<elements>
    <element attribute="value1">
        <subelement attribute="value2" />
    </element>
</elements>

这就是:

<elements>
    <element attribute="value1">
        <and>
            <or>
                <subelement attribute="value2" />
                <subelement attribute="value3" />
            </or>
            <or>
                <subelement attribute="value4" />
                <subelement attribute="value5" />
            </or>
        </and>
    </element>
</elements>

(上面的例子等同于(value2或value3)AND(value4或value5)

我尝试使用xsd.exe从XML创建XSD文件,然后使用.cs类,但这对我的需求来说还不够,因为我需要一些可以有任意深度的东西。

我如何在C#中将其建模为类?我或许正在考虑某种流利的建设者模式?

谢谢,

理查德

P.S。任何能够提出验证由这样的类结构创建的规则的方法的人都会得到一个/抱抱:)

1 个答案:

答案 0 :(得分:0)

以下架构定义正确验证了所有3个XML示例。不幸的是,当XSD.exe尝试将其转换为C#代码时,它会因堆栈溢出异常而崩溃。但是,将xsd文件设置为架构inside visual studio会使xml编辑器正常工作,并指出xml违反的任何验证规则。

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="schema"
    targetNamespace="http://tempuri.org/schema.xsd"
    elementFormDefault="qualified"
    xmlns="http://tempuri.org/schema.xsd"
    xmlns:mstns="http://tempuri.org/schema.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:element name="elements">
    <xs:complexType>
      <xs:sequence>
        <xs:element name ="element" minOccurs="0" maxOccurs="unbounded">
          <xs:complexType>
            <xs:choice>
              <xs:element name="and" type="subLogic"/>
              <xs:element name="or" type="subLogic"/>
              <xs:element name="subelement" type ="subElement" />
            </xs:choice>
            <xs:attribute name="attribute"/>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="subLogic">
    <xs:choice minOccurs="1" maxOccurs="unbounded">
      <xs:element name="subelement" type="subElement"/>
      <xs:element name="and" type="subLogic"/>
      <xs:element name="or" type="subLogic"/>
    </xs:choice>
  </xs:complexType>

  <xs:complexType name="subElement">
    <xs:attribute name="attribute"/>
  </xs:complexType>
</xs:schema>

以下是xml的更改版本,以使visual studio对其进行验证并启用智能感知。您可以选择在xml文件的适当位置schemas选择器下选择xsd文件。

<?xml version="1.0" encoding="utf-8" ?>
<elements 
    xmlns="http://tempuri.org/schema.xsd"
    xmlns:mstns="http://tempuri.org/schema.xsd">
  <element  attribute="value1">
    <and>
      <or>
        <subelement attribute="value2" />
        <subelement attribute="value3" />
      </or>
      <or>
        <subelement attribute="value4" />
        <subelement attribute="value5" />
      </or>
    </and>
  </element>
</elements>

在不知道你所代表的内容或类需要做什么的情况下,这是一个模仿XSD的基本布局。您从此类生成的XML可能无法验证,但只需向类和属性添加正确的属性,以便所有内容都显示正确的名称,布局正确。

class SubLogic
{
}

abstract class CollectionType : SubLogic
{
    public SubLogic[] Sub { get; set; }
}

class And : CollectionType
{
}

class Or : CollectionType
{
}

class SubElement : SubLogic
{
    public string Attribute { get; set; }
}

[XmlRoot("elements")]
class ElementCollection
{
    public Element[] Elements {Get;Set}
}

class Element
{
    public SubLogic Sub { Get; set;}
}