2

Consider the following 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>

Note that the following is also valid:

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

And so is this:

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

(The above example would equate to (value2 or value3) AND (value4 or value5)

I tried using xsd.exe to create a XSD file from the XML and then a .cs class but it was not sufficient for my needs as I need something that can have an arbitrary depth.

How would I model this in C# as classes? I'm thinking perhaps along the lines of some sort of fluent builder pattern?

Thanks,

Richard

P.s. Anyone who can come up with a way to validate the rules created by such a class structure gets a /hug :)

Richard
  • 603
  • 5
  • 14
  • Yes, I looked into that but my head exploded. I hear this is common when investigating expression trees :) – Richard Apr 02 '14 at 22:05

1 Answers1

0

The following schema definition correctly validates all 3 of your XML examples. Unfortunately XSD.exe crashes with a stack overflow exception when it tries to turn it in to C# code. However setting the xsd file as the schema inside visual studio makes the xml editor work correctly and will point out any validation rules that your xml violates.

<?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>

Here is a changed version of the xml to make visual studio validate it and enables intellisense. Just be shure you have your xsd file selected under the schemas selector in the properites for the xml file.

<?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>

Without knowing more of what you are representing or what the classes will need to do here is a basic layout that mimic's the XSD. XML you generate from this class will likely not validate, but it is just a matter of adding the correct attributes to the classes and properties so everything shows up with the correct name, the layout is correct.

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;}
}
Community
  • 1
  • 1
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431