Reputation: 2892
I am trying to figure out the correct cast type for the "Parent" property of an object of type XmlSchemaSimpleType. The below code is always returning "" as the "parent" variable is validated to null. Can anyone please help how to retrieve minOccurs from the parent of a simpleType ? Thank you!
private string GetMinOccurs(XmlSchemaSimpleType xsdSimpleType)
{
var parent = xsdSimpleType.Parent as XmlSchemaElement;
if (parent == null) return "";
return parent.MinOccurs.ToString();
}
An example of my XSD is:
<xsd:complexType name="New_Type">
<xsd:sequence>
<xsd:element name="Amount" type="Amount_Type" minOccurs="1" maxOccurs="1" />
<xsd:element name="Name" type="Name_Type" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="Amount_Type">
<xsd:annotation>
<xsd:documentation>Amount</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="12" />
</xsd:restriction>
</xsd:simpleType>
Upvotes: 3
Views: 1171
Reputation: 8741
Like I said in the comment of your previous question. the Parent
property of an XmlSchemaSimpleType
does not work like you think. It looks like you are hoping it will return the <element>
that has a type of the XmlSchemaSimpleType
you are specifying.
But consider this situation:
<xsd:complexType name="New_Type">
<xsd:sequence>
<xsd:element name="Amount" type="Amount_Type" minOccurs="1" maxOccurs="1" />
<xsd:element name="OtherAmount" type="Amount_Type" minOccurs="10" maxOccurs="15" />
<xsd:element name="Name" type="Name_Type" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="Amount_Type">
<xsd:annotation>
<xsd:documentation>Amount</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="12" />
</xsd:restriction>
</xsd:simpleType>
Which would it return as there are 2 different elements with the same type? As you can see from this example, a type can be used multiple times throughout an XSD and each occurance can have a different MinOccurs
value. If you want to get the MinOccurs
, you need to find the exact <element>
you want, even if the type is used just once. But to do that you need to know where it is in the XSD.
This blog is a few years old, but I think helps with the point. You basically have to find the complex type using XmlSchemaSet.GlobalTypes[]
, then you need to look through the Particle
property. In your case, there will be a single XmlSchemaSequence
object in there (you'll probably need to cast). Then you need to look through the items property to find your Amount
element. From there (after another cast), you can get MinOccurs.
If you don't know exactly what you are looking for, all of the collections in the XmlSchemaObject
properties do have GetEnumerator
methods, so you can use foreach
to help scan everything. None are generic though so you need to do a lot of casting, but this is basically what you have to do:
foreach (DictionaryEntry item in set.GlobalTypes)
{
// set.GlobalTypes.GetEnumerator returns an object, so you need to cast to DictionaryEntry
// DictionaryEntry.Key and DictionaryEntry.Value are objects too so you need to cast again
// Particle is an XmlSchemaObject, so you need to cast to an XmlSchemaSequence
var seq = (XmlSchemaSequence)((XmlSchemaComplexType)item.Value).Particle;
// XmlSchemaSequence.Items also returns an XmlSchemaObject so you need to cast again to XmlSchemaElement.
foreach (XmlSchemaElement i in seq.Items)
{
if (i.SchemaTypeName == new XmlQualifiedName("Amount_Type"))
{
Console.WriteLine(i.MinOccursString);
}
}
}
But this is just an example to show how to get where you want to go. You need to do some type checking before each of the casts in case it fails. For example, var seq = (XmlSchemaSequence)((XmlSchemaComplexType)item.Value).Particle;
will throw an exception after it gets to the second type in your XSD since it is not a complex type, it is a simple type.
A LINQ solution might be easier if you know exactly what you want:
var xDoc = XDocument.Load("your XSD path");
var ns = XNamespace.Get(@"http://www.w3.org/2001/XMLSchema");
var minOccurs = from element in xDoc.Descendants()
where (String)element.Attribute("type") == "Amount_Type"
select (String)element.Attribute("minOccurs");
This method at least lets you scan the document quickly for any type that matches your Amount_Type
and grabs the minOccurs (or returns null of there is no minOccurs
attribute).
Upvotes: 1