Reputation: 561
I'm trying to parse a custom XSD to build a list of elements which have custom attributes defined. I've pasted a sample node from my XSD below. In my case, I'm trying to build a list of all elements (simple and complex types) that have been marked as static. Sample -
<xs:element name="ATestEnum">
<xs:annotation>
<xs:appinfo>
<ConfigurationMemberMetadata>
<Static>False</Static>
</ConfigurationMemberMetadata>
</xs:appinfo>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Sample1" />
<xs:enumeration value="Sample2" />
</xs:restriction>
</xs:simpleType>
</xs:element>
I just can't figure out a way to query 'inside' an element for the properties I need. I've gotten as far as this -
var doc = XDocument.Load(schemaFileName);
foreach (var element in doc.Descendants(xs + "element"))
{
Console.WriteLine(element.Attribute("name").Value);
}
This gives me a list of all the elements in the xsd but not the specific property (ConfigurationMemberMetadata) that I need to check. I see the element.Annotation(type) method but how do I cast it to extract the fields I'm looking for?
I also tried using the XmlTextReader and reading the schema, compiling the schemaset and iterating through the elements but that doesn't help either.
Can someone point me in the right direction? I'm very new to xml parsing and would really appreciate your help! Thanks.
Upvotes: 3
Views: 5218
Reputation: 16806
Make use of an Xpath query to selectively find only the nodes that you are interested in ('Static' nodes).
Here is a good example of how to do that: http://support.microsoft.com/kb/308333
If you need practice with XPath, use this "testbed" to get acquainted with its syntax: http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm
Using your sample XML, this Xpath query will find all "Static" nodes:
/xml/xs:element/xs:annotation/xs:appinfo/ConfigurationMemberMetadata/Static
Upvotes: 2
Reputation: 21638
You have to use something like this:
XmlReader reader = XmlReader.Create(@"D:\....\your-file.xsd");
XDocument doc = XDocument.Load(reader);
XmlNamespaceManager ns = new XmlNamespaceManager(reader.NameTable);
ns.AddNamespace("", "http://tempuri.org/XMLSchema.xsd");
XNamespace xs = "http://www.w3.org/2001/XMLSchema";
foreach (var element in doc.Descendants(xs + "element")) { Console.WriteLine(element.Attribute("name").Value); }
foreach (XElement element in (IEnumerable)doc.XPathEvaluate("//ConfigurationMemberMetadata")) { Console.WriteLine(element.Name); }
Annotations are not showing up in the infoset, they're something else. To get to your element, use an XPath.
One thing to pay attention is the namespace you associate with your prefix. Typically, in an XSD file, the default namespace matches the target namespace, which is why I've set a dummy namespace - update to match yours. If you don't have a default namespace, just set the uri to the empty string as well.
Here is the XSD I've used with the code above:
<?xml version="1.0" encoding="utf-8" ?>
<!--W3C Schema generated by QTAssistant/W3C Schema Refactoring Module (http://www.paschidev.com)-->
<xs:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ATestEnum">
<xs:annotation>
<xs:appinfo>
<ConfigurationMemberMetadata>
<Static>False</Static>
</ConfigurationMemberMetadata>
</xs:appinfo>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Sample1"/>
<xs:enumeration value="Sample2"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:schema>
Upvotes: 4