How to parse xs: annotation from xs: using selection with System.Xml.Schema

I am trying to add an annotation element inside an xs: selection. According to the xs: select syntax, this is possible. I couldn't find an annotated sample inside BTW. My current version of the xsd file contains the element:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.es.de/es3/flex/simple"
             elementFormDefault="qualified"
             xmlns="http://www.es.de/es3/flex/simple"
             xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
             xmlns:xs="http://www.w3.org/2001/XMLSchema"
             xmlns:flex="http://www.es.de/es3/flex/flexBase">

    <xs:import namespace="http://www.es.de/es3/flex/flexBase" />

    <xs:element name="ESS3754">
        <xs:complexType>
            <xs:choice>
                <xs:annotation>
                    <xs:appinfo>
                        <flex:ControlHeadline>Headline_VVVVV</flex:ControlHeadline>
                        <flex:helpText>HelpText_VVVVV</flex:helpText>
                    </xs:appinfo>
                </xs:annotation>
                <xs:element name="String1" type="xs:string" minOccurs="1" maxOccurs="1"/>
            </xs:choice>
        </xs:complexType>
    </xs:element>

</xs:schema>

      

However, when parsing an xsd file, the object annotation is System.Xml.Schema.XmlSchemaChoice

always null.

Code part:

public List<FSBaseItem> Parse( XmlTextReader xsdReader )
        {
            try
            {
                // prepare schema set for schema validation and raw template xsd "enrichment"
                XmlSchemaSet schemaSet = new XmlSchemaSet();
                schemaSet.ValidationEventHandler += ValidationCallbackOne;

                // include base schema
                XmlSchema baseXsd = FlexXmlSchemaReader.ReadBase();
                schemaSet.Add( baseXsd );

                // The Read method will throw errors encountered on parsing the schema
                XmlSchema xsd = XmlSchema.Read( xsdReader, ValidationCallbackOne );
                schemaSet.Add( xsd );

                // The Compile method will throw errors encountered on compiling the schema
                schemaSet.Compile();

                // create root
                FSElement rootElement = new FSElement( this.GetNewId() );
                // traverse body
                this.TraverseSOM( xsd, rootElement );
                // validate
                this.ValidateFSItems( rootElement.Items );
                // init lists containers with minimum elements
                InitEmptyFEListItems( rootElement );                

                return rootElement.Items;
            }
            finally
            {
                xsdReader.Close();
            }
        }

      

Already at the start, the annotation text of the select element is null :( Can anyone give some working selection or add some hints? Any help would be appreciated.

+3


source to share


2 answers


Annotations can of course be placed inside xs: choice. Have a look at the following xsd taken from Inline Annotated Schema

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
  jaxb:version="1.0" jaxb:extensionBindingPrefixes="xjc">
    <xs:annotation>
        <xs:appinfo>
            <jaxb:globalBindings>
                <xjc:superClass name="com.syh.Shape"/>
            </jaxb:globalBindings>
        </xs:appinfo>
    </xs:annotation>
    <xs:element name="Widgets">
        <xs:complexType>
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:annotation>
                    <xs:appinfo>
                        <jaxb:property name="Shapes"/>
                    </xs:appinfo>
                </xs:annotation>
                <xs:element name="Rectangle" type="Rectangle"/>
                <xs:element name="Square" type="Square"/>
                <xs:element name="Circle" type="Circle"/>
            </xs:choice>
         </xs:complexType>
    </xs:element>
    <xs:complexType name="Rectangle">
        <xs:sequence>
            <xs:element name="Width" type="xs:integer"/>
            <xs:element name="Height" type="xs:integer"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Square">
        <xs:sequence>
            <xs:element name="Length" type="xs:integer"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Circle">
        <xs:sequence>
            <xs:element name="Radius" type="xs:integer"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

      

Adapting a similar strategy to your xsd gives something like the following:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.es.de/es3/flex/simple"
             elementFormDefault="qualified"
             xmlns="http://www.es.de/es3/flex/simple"
             xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
             xmlns:xs="http://www.w3.org/2001/XMLSchema"
             xmlns:flex="http://www.es.de/es3/flex/flexBase">

  <xs:import namespace="http://www.es.de/es3/flex/flexBase" />

  <xs:element name="ESS3754">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:annotation>
          <xs:appinfo>
            <flex:ControlHeadline>Headline_VVVVV</flex:ControlHeadline>
            <flex:helpText>HelpText_VVVVV</flex:helpText>
          </xs:appinfo>
        </xs:annotation>
        <xs:element name="String1" type="xs:string" minOccurs="1" maxOccurs="10"/>
        <xs:element name="NewlyAdded" type="Coordinate" minOccurs="1" maxOccurs="10"/>
      </xs:choice>
    </xs:complexType>    
  </xs:element>
  <xs:complexType name="Coordinate">
  <xs:sequence>
    <xs:element name="LocationX" type="xs:integer"/>
    <xs:element name="LocationY" type="xs:integer"/>
    <xs:element name="LocationZ" type="xs:integer"/>
  </xs:sequence>
</xs:complexType>    

</xs:schema>

      

and the xsd is perfectly correct and looks like this in Visual Studio [XSD] Desginer:

enter image description here

Update 1



I agree that the debugger shows the annotation of the object as null [I couldn't find it, but I should] and it's pretty tricky. I have restored the document using code and you can annotate your element with the following workaround: Consider the following XSD which does not have XmlSchemaChoice and is saved as stack-problem2.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.es.de/es3/flex/simple"
             elementFormDefault="qualified"
             xmlns="http://www.es.de/es3/flex/simple"
             xmlns:mstns="http://tempuri.org/XMLSchema.xsd"
             xmlns:xs="http://www.w3.org/2001/XMLSchema"
             xmlns:flex="http://www.es.de/es3/flex/flexBase">

  <xs:import namespace="http://www.es.de/es3/flex/flexBase" />




  <xs:complexType name="Coordinate">
    <xs:sequence>
      <xs:element name="LocationX" type="xs:integer"/>
      <xs:element name="LocationY" type="xs:integer"/>
      <xs:element name="LocationZ" type="xs:integer"/>
    </xs:sequence>
  </xs:complexType>  
</xs:schema>

      

Now you can load this into memory and programmatically add annotations to the XmlSchemaChoice element:

public void Parse()
{
    try
    {
        XmlTextReader reader2 = new XmlTextReader(@"stack-problem2.xsd");
        XmlSchema myschema2 = XmlSchema.Read(reader2, ValidationCallback);


        var simpleAnotation = new XmlSchemaAnnotation();
        simpleAnotation.Id = "Lost Anotation";

        // <xs:complexType name="ESS3754">
        XmlSchemaComplexType complexType = new XmlSchemaComplexType();
        myschema2.Items.Add(complexType);
        complexType.Name = "ESS3754";

        // <xs:choice minOccurs="1" maxOccurs="1">
        XmlSchemaChoice choice = new XmlSchemaChoice();
        complexType.Particle = choice;
        choice.MinOccurs = 1;
        choice.MaxOccurs = 1;

        XmlSchemaElement elementSelected = new XmlSchemaElement();
        choice.Items.Add(elementSelected);
        elementSelected.Name = "String1";

        AnnonateMyComplexType(choice); 

        FileStream file = new FileStream(@"satck-solution.xsd", FileMode.Create, FileAccess.ReadWrite);
        XmlTextWriter xwriter = new XmlTextWriter(file, new UTF8Encoding());
        xwriter.Formatting = Formatting.Indented;
        myschema2.Write(xwriter);
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}

public static void AnnonateMyComplexType(XmlSchemaChoice xmlSchemaComplexType)
{

    XmlSchemaAnnotation myCustomAnnotation = new XmlSchemaAnnotation();
    xmlSchemaComplexType.Annotation = myCustomAnnotation;

    // <xs:documentation>State Name</xs:documentation>
    XmlSchemaDocumentation schemaDocumentation = new XmlSchemaDocumentation();
    myCustomAnnotation.Items.Add(schemaDocumentation);
    schemaDocumentation.Markup = TextToNodeArray("Headline_VVVVV");

    // <xs:appInfo>Application Information</xs:appInfo>
    XmlSchemaAppInfo appInfo = new XmlSchemaAppInfo();
    myCustomAnnotation.Items.Add(appInfo);
    appInfo.Markup = TextToNodeArray("Headline_VVVVV");

}

static void ValidationCallback(object sender, ValidationEventArgs args)
{
    if (args.Severity == XmlSeverityType.Warning)
        Console.Write("WARNING: ");
    else if (args.Severity == XmlSeverityType.Error)
        Console.Write("ERROR: ");

    Console.WriteLine(args.Message);
}

      

Running above will return the following XSD file:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="http://www.es.de/es3/flex/simple" xmlns:flex="http://www.es.de/es3/flex/flexBase" xmlns:mstns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" targetNamespace="http://www.es.de/es3/flex/simple" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:import namespace="http://www.es.de/es3/flex/flexBase" />
  <xs:complexType name="Coordinate">
    <xs:sequence>
      <xs:element name="LocationX" type="xs:integer" />
      <xs:element name="LocationY" type="xs:integer" />
      <xs:element name="LocationZ" type="xs:integer" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="ESS3754">
    <xs:choice minOccurs="1" maxOccurs="1">
      <xs:annotation>
        <xs:documentation>Headline_VVVVV</xs:documentation>
        <xs:appinfo>Headline_VVVVV</xs:appinfo>
      </xs:annotation>
      <xs:element name="String1" />
    </xs:choice>
  </xs:complexType>
</xs:schema>

      

So, to answer your first question: Yes, the annotation can definitely be placed inside XmlSchemaChoice elements (either through code or directly) [Not necessarily outside xmlSchemaChoice as the top element based on your experiment] and to solve your second problem: [I had the same experience as yours! It shows annotation as null, although it doesn't)

+4


source


For anyone else who comes across this issue, I found by mirroring the classes of the System.Xml.Schema namespace, which, after the schema is compiled, the element annotations are copied to their children.



So Vytas999 should (as I could) find its missing annotation by checking the XmlSchemaParticle objects in the XmlSchemaChoice.Items property.

0


source







All Articles