Question

I have searched through S/O but not found anything to resolve my issue (though C# - Parsing XSD schema - get all elements to combobox has helped a little).
In the XSD file below, I need to get the name of the nested elements (SectionA and then to AX010_1, AX040_1.. then to SectionB and to BX010_1, BX070_1 etc)

How can I access the nested elements?

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="Vehicle">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Ford" minOccurs="0" maxOccurs="1">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="SectionA" minOccurs="0" maxOccurs="1">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="AX010_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="AX040_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="AX050_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="AX190_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="A080_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="AX230F_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="AX230G_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="AX230GNOTE_1" type="ExplanatoryText" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="AX230H_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="AX230HNOTE_1" type="ExplanatoryText" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="AX230J_1" type="ExplanatoryText" minOccurs="0" maxOccurs="1"/>
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                            <xs:element name="SectionB" minOccurs="0" maxOccurs="1">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="BX010_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="BX070_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="BX350N_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="BX350NNOTE_1" type="ExplanatoryText" minOccurs="0" maxOccurs="1"/>
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                            <xs:element name="SectionC" minOccurs="0" maxOccurs="1">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="C010_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="C010_2" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="C010_4" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="CF030_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                            <xs:element name="SectionD" minOccurs="0" maxOccurs="1">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="D010_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="D030_2" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                        <xs:element name="D560_1" type="Dollar" minOccurs="0" maxOccurs="1"/>
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>
Was it helpful?

Solution 2

When reading XSD files, there are two things to consider:

You need to find your way manually in the XSD file:

  • find the complexType node
  • find the sequence
  • find the element
  • and so on

It is not difficult, but tedious. If you will need this often, than you could implement the methods as extensions. The code that follows could be optimised regarding the error handling.

A possible solution using LINQ2XML can look like this:

try
{           
    var xsd = XDocument.Load("d:\\temp\\input.xsd");
    var ns = xsd.Root.GetDefaultNamespace();
    var prefix = xsd.Root.GetNamespaceOfPrefix("xs");
    // get Vehicle
    var vehicle = xsd.Root.Element(prefix + "element");
    // get sequence for Ford
    var sections = vehicle.Element(prefix + "complexType")
                        .Element(prefix + "sequence")
                        // the Ford element
                        .Element(prefix + "element")
                        .Element(prefix + "complexType")
                        .Element(prefix + "sequence")
                        // elements
                        .Elements(prefix + "element").ToList();
    foreach (var section in sections)
    {
        Console.WriteLine(section.Attribute("name").Value);
        // for each section element
        var items = section.Element(prefix + "complexType")
                            .Element(prefix + "sequence")
                            // take the test elements
                            .Elements(prefix + "element");
        foreach (var item in items)
        {
            Console.WriteLine(item.Attribute("name").Value);
            // access another attributes or values here
        }
    }
}
catch (Exception exception)
{
    Console.WriteLine(exception.Message);
}

The output is:

SectionA
AX010_1
AX040_1
AX050_1
AX190_1
A080_1
AX230F_1
AX230G_1
AX230GNOTE_1
AX230H_1
AX230HNOTE_1
AX230J_1
SectionB
BX010_1
BX070_1
...

OTHER TIPS

An xsd is nothing more than an xml with a namespace

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(@"C:\myXsd.xsd");

XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema");

XmlNodeList nodes =
    xmlDoc.SelectNodes("//xs:element[starts-with(@name, 'Section')]/*//xs:element", nsmgr);

List<string> namesList = new List<string>();

foreach (XmlNode node in nodes)
{
    namesList.Add(node.Attributes["name"].Value);
}

should yield the desired output.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top