[xsd-users] XInclude support?

Boris Kolpackov boris at codesynthesis.com
Sat Feb 9 12:13:43 EST 2008


Hi Lane,

Lane Wimberley <techlane64 at gmail.com> writes:

> Hi Boris.  I apologize if this has been asked before (I searched, but have
> only been XSDing for a couple months now so am still a neophyte), but is
> there, or will there be support for XInclude (assuming this is still
> on-track with W3C)?

XInclude is a generic XML fragment inclusion mechanism and, if supported,
is normally handled by the XML parser transparently. That is you get a
DOM document or SAX events as if the xi:include elements were never
there and instead the document fragments were included in the XML
document directly. From my experience, however, XInclude is not widely
used.

Now about support in XSD, or rather in the underlying XML parser that
it uses. Current version of Xerces-C++ (2.8.0) does not support XInclude
thought it is probably not too hard to create a post-processor for DOM
that will handle basic cases and then feed the result to the generated
parsing functions. Upcoming Xerces-C++ 3.0.0 provides built-in support
for XInclude in DOM parsers (and that's what the C++/Tree mapping is
using), however, XInclude elements are handled after XML Schema
validation which may or may not be what you want.


> My goal is to create an interface that supports use of an XML-based
> configuration file that can include another config file.  For example, if a
> site has a site-wide configuration with global defaults for run-time
> application parameters, etc., but a particular user of the application
> wishes to over-ride some of those, he or she would be able to construct a
> simple personal config file that first includes the site config file, then
> simply re-defines a few parameters that they care about.

Hm, you are not going to get any "redefine logic" with XInclude. It is
a generic XML inclusion mechanism that doesn't know anything about the
semantics of the data being included.


> Perhaps there is already some simpler way to accomplish this ... ?  Or, is
> it simply a matter of including/importing the XInclude schema into mine, and
> then processing the "include" elements myself "by hand?"

Yes, that's one way to do it. However, I would probably ditch XInclude
and implement my own inclusion mechanism that is part of the vocabulary.
After all, your inclusion elements will only make sense at certain points
and have an added semantics of overriding things that were defined/include
before. Here is how I would approach it. Let's say we have the following
types for our "Configuration" vocabulary:

<complexType name="Property">
  <sequence>
    <element name="name" type="string"/>
    <element name="value" type="string"/>
  </sequence>
</complexType>

<complexType name="Configuration">
  <sequence>
    <element name="include" type="string" minOccurs="0" maxOccurs="unbounded"/>
    <element name="property" type="Property" minOccurs="0" maxOccurs="unbounded"/>
  </sequence>
</complexType>

<element name="configuration" type="Configuration"/>

That is, our configuration XML file consists of an optional sequence
of 'include' elements followed by an optional sequence of 'property'
elements which are defined as name-value pairs. The subsequent
properties override previous values of properties with the same name.
Two major differences with XInclude here: first the place where the
users of our vocabulary can use include elements is restricted to the
beginning of the file. With XIclude the user can use it in any place,
for example to include a value for the 'name' or 'value' element
(unless you explicitly specify where xi:include elements can be used
in your schema).

The next step is to process the include elements so that the users
of our object model (as generated by XSD) only deal with lists of
properties. The cleanest way to do this is to customize the
Configuration class by inheriting from the generated version and
adding include processing code to the parsing constructors. This
way everything will be handled completely transparently for the
user. For an idea on how to do all this, see the 'wildcard' example
in the examples/cxx/tree/custom/ directory as well as the C++/Tree
Mapping Customization Guide:

The 'wildcard' example overrides the parsing c-tor and serialization
operator to extract data matched by an XML Schema wildcard. In your
case, your parsing c-tor could perform the following tasks instead:

1. Allow the base parser to extract the data from DOMElement and
   fill in the include and property sequences.

2. Create an std::map<name, value> instance. This will automatically
   take care of the override logic as long as you insert the data in
   the correct order.

3. Iterate over the include sequence and parser each included file
   into an object model (at this stage this constructor can be called
   recursively if the included files contain any include elements
   themselves). Once you get the object model for a file, iterate over
   the property sequence and copy the properties into the map.

4. After all include elements are handled, iterate over the property
   sequence and copy the properties into the map. The resulting map
   contains the final property values. You can now clear the property
   sequence and copy properties from the map back into it. Or, you can
   go one step further in customizing the Configuration class and make
   it store the properties not as a sequence of name value pairs but as
   a map. Users of your object model will probably find this handy. If
   you do this then you also don't need to inherit from the generated
   Configuration class (you can just use it the implementation of your
   c-tor) which has an added benefit of not exposing the include
   sequence to the users.


HTH,
Boris




More information about the xsd-users mailing list