BestPracticeXmlBeansSubstitutionGroups

Motivation

Given the example of programmitically creating a SamplingFeature and adding this to a gml:FeatureCollection. "sa:SamplingFeature" is a member of the substitution group "gml:_Feature", hence it is not possible to create the "!SamplingFeature" with a single method call (such as collection.addNewSamplingFeature()). Here is a short example how this can be achieved using XmlCursors and a few lines of code. It can be used for any substitution group you want to programmatically create. HELP Note that this applies for valid substitutions of a substitution group which are not available at the time of schema compilation (an example is OGC Sampling 1.0 [as the extension schema] with SamplingPoint as a valid substitution for GML 3.1 [as the base schema] gml:_Feature). Here, Available at the time of schema compilation means that the contens of both schemas need to be compiled into one resulting jar. Having a .jar with the compiled extension schema on the classpath while compiling the base schema is not sufficient.

Dealing with unresolvable but valid substitutionGroup members

Creating substitutionGroup members

The starting point is the creation the FeatureCollection and the SamplingFeature:
      FeatureCollectionDocument doc = FeatureCollectionDocument.Factory.newInstance();
      FeaturePropertyType member = FeatureCollectionDocument.Factory.newInstance().addNewFeatureCollection().addNewFeatureMember();

      SamplingFeatureDocument samplingFeature = SamplingFeatureDocument.Factory.newInstance();
      SamplingFeatureType feature2 = samplingFeature.addNewSamplingFeature();
      StringOrRefType desc = feature2.addNewDescription();
      desc.setStringValue("test");
      member.setFeature(feature2);

As no method like "member.addNewSamplingFeature()" is available, it must use "member.setFeature()". Therefore this would result in:
<gml:_FeatureCollection xmlns:gml="http://www.opengis.net/gml">
  <gml:featureMember>
    <gml:_Feature xsi:type="sa:SamplingFeatureType" xmlns:sa="http://www.opengis.net/sampling/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <gml:description>test</gml:description>
    </gml:_Feature>
  </gml:featureMember>
</gml:_FeatureCollection>

Obviously we need to replace the "gml:_Feature" with "sa:SamplingFeatureType" to make the resulting document valid. This can be done by using the XMLBeansTools.qualifySubstitutionGroup(...) method:
      ...
      member.setFeature(feature2);
      XMLBeansTools.qualifySubstitutionGroup(member.getFeature(), SamplingFeatureDocument.type.getDocumentElementName(), null)

HELP Note the usage of XMLBeansTools class. It is available in the 52n-oxf-2.0/52n-oxf-xmlbeans module. Also note that the last argument is null. This allows the method to skip the built-in XmlObject.substitute(...) mechanism as we know that it will fail (due to unavailability of the SamplingFeature type during GML schema compilation time). For convenience, here are the contents of the "qualifySubstitutionGroup(...)" method:
    public static XmlObject qualifySubstitutionGroup(XmlObject xobj, QName newInstance, SchemaType newType) {
       XmlObject substitute = null;
       if (newType != null) {
          substitute = xobj.substitute(newInstance, newType);
           if (substitute != null && substitute.schemaType() == newType &&
                 substitute.getDomNode().getLocalName().equals(newInstance.getLocalPart())) {
              return substitute;
           }
       }
       
        XmlCursor cursor = xobj.newCursor();
        cursor.setName(newInstance);
        QName qName = new QName("http://www.w3.org/2001/XMLSchema-instance", "type");
        cursor.removeAttribute(qName);
        cursor.dispose();
        
        return null;
    }

The method will return null if the cursor.setName(...) technique is applied. This is done because the returned object (e.g. xobj, or cursor.getObject()) is disconnected and thus can no longer be manipulated. So its just null to make sure you won't do that. HELP Sometimes the famous xsi:type is added when using substitution groups. This methods also removes it as it is not needed.

The overall result is a valid document, using "sa:SamplingFeature". This method can be applied to any substitution group you are dealing with by only providing the XmlObject instance and target QName.

<gml:_FeatureCollection xmlns:gml="http://www.opengis.net/gml">
  <gml:featureMember>
    <sa:SamplingFeature xmlns:sa="http://www.opengis.net/sampling/1.0">
      <gml:description>test</gml:description>
    </sa:SamplingFeature>
  </gml:featureMember>
</gml:_FeatureCollection>

Of course, the same procedure can be applied to gml:_FeatureCollection. Give it a try (by replacing it with sa:SamplingFeatureCollection).

Attached find a working example. You need 52n-xml-gml-v311, 52n-xml-sampling-v100, 52n-xml-filter-v20, 52n-oxf-xmlbeans and log4j on your buildpath.

Parsing substitutionGroup members with unresolved valid substitutions

HELP TBD. We have created a work around for document validation with unresolved substitutionGroup members. Located within the XMLBeansParser class of 52n-oxf-2.0/52n-oxf-xmlbeans module. Description tbd.

Creating substitutionGroup members with compiled-in valid substitutions

There are also valid substitutions which are available at schema compilation time and thus can be easily substituted. an example is a substitution for fes:logicOps such as fes:And. Here, we are able to continue using the object after successfully qualifying it.
      FilterDocument filterDoc = FilterDocument.Factory.newInstance();
      FilterType filter = filterDoc.addNewFilter();
      XmlObject andOp = XMLBeansTools.qualifySubstitutionGroup(filter.addNewLogicOps(), AndDocument.type.getDocumentElementName(), BinaryLogicOpType.type);
      XmlObject anotherAndOp = XMLBeansTools.qualifySubstitutionGroup(((BinaryLogicOpType) andOp).addNewLogicOps(),
            AndDocument.type.getDocumentElementName(), BinaryLogicOpType.type);

Metadata

  • Topic created by: MatthesRieke
  • Topic created on: 2012-08-10
Topic revision: r5 - 14 Aug 2012, MatthesRieke
Legal Notice | Privacy Statement


This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding Wiki? Send feedback