Partager via


XML Schema Facets

I have received a number of requests over a period of time asking how to get all the facets defined on simple types or complex types with simple content in an XML Schema. I recently wrote a code sample for the same and I thought i will post it for wider consumption. The code sample will handle restrictions on lists, unions as well as facets defined on base types.

 public static void GetSchemaTypeFacets(XmlSchemaType schemaType) {

  if (schemaType == null || schemaType.Datatype == null) { //Complex type with complex content
   return;
  }

  XmlSchemaSimpleType st = schemaType as XmlSchemaSimpleType;
  if (st != null) {
   GetSimpleTypeFacets(st);
  }
  else { //Complex type simple content
   XmlSchemaComplexType ct = schemaType as XmlSchemaComplexType;
   Debug.Assert(ct != null);
   XmlSchemaSimpleContent simpleContent = ct.ContentModel as XmlSchemaSimpleContent;
   Debug.Assert(simpleContent != null);
   XmlSchemaSimpleContentRestriction simpleRest = simpleContent.Content as XmlSchemaSimpleContentRestriction;
   if (simpleRest != null) { //Can also be simple content extension
    PrintFacets(simpleRest.Facets);
   }
   GetSchemaTypeFacets(ct.BaseXmlSchemaType);

  }
 }

 public static void GetSimpleTypeFacets(XmlSchemaSimpleType st) {
   if (st == null || st.QualifiedName.Namespace == XmlSchema.Namespace) { //Built-in type, no user-defined facets
     return;
   }
   switch(st.Datatype.Variety) {
    case XmlSchemaDatatypeVariety.List:
      XmlSchemaSimpleType itemType = (st.Content as XmlSchemaSimpleTypeList).BaseItemType;
      GetSimpleTypeFacets(itemType);
    break;
 
    case XmlSchemaDatatypeVariety.Union:
      XmlSchemaSimpleTypeUnion union = st.Content as XmlSchemaSimpleTypeUnion;
      foreach(XmlSchemaSimpleType stu in union.BaseMemberTypes) {
        GetSimpleTypeFacets(stu);
      }
    break;

    case XmlSchemaDatatypeVariety.Atomic:
      XmlSchemaSimpleTypeRestriction rest = st.Content as XmlSchemaSimpleTypeRestriction;   
      PrintFacets(rest.Facets);
    break;

    default:
    break;  
  }

  if (st.BaseXmlSchemaType != null) { //Chain to the base type
   GetSimpleTypeFacets(st.BaseXmlSchemaType as XmlSchemaSimpleType); //BaseType of a simple type is always a simple type
  }
 
 }

 private static void PrintFacets(XmlSchemaObjectCollection facets) {
  foreach(XmlSchemaFacet facet in facets) {
   Console.WriteLine(facet.GetType().ToString() + " " + facet.Value);
  }    
 }

Let me know if you have any questions.

-Priya Lakshminarayanan

Comments

  • Anonymous
    June 02, 2007
    Hi There, I found Linq to XSD very useful particularly the great support for Choice xsd element! But one thing I found annoying. The Properties of the Type, from which an XML Element is derived, are 'hidden' under the Content Prpoerty! Here is an example: public partial class UtilityPolicyAssertion : XTypedElement, IXMetaData { [DebuggerBrowsable(DebuggerBrowsableState.Never)] private UtilityPolicyAssertionType ContentField; .... public UtilityPolicyAssertionType Content { get { return ContentField; } } The Annoying thing is that if I want to access an ID Property defined in UtilityPolicyAssertionType I need to use: UtilityPolicyAssertion myAssertion; .... myAssertion.Content.ID; Why not allowing the simple myAssertion.ID; ?? Why the generated code does not 'preserve' XSD fedility and generate something like: public partial class UtilityPolicyAssertion : XTypedElement, IXMetaData, UtilityPolicyAssertionType  ? Is there any work around to get the generated Class to inherit from the Type? What is the design behind having the .Content Property? (and not enhiriting from the ElementType?) Any help is appreciated. Thanks Regards Karim