[xsd-users] Attempting to access attribute xml:base.

Jeroen N. Witmond jnw at xs4all.nl
Sat Jan 13 11:24:53 EST 2007


Hi Boris

"Boris Kolpackov" <boris at codesynthesis.com> writes:

> Jeroen N. Witmond <jnw at xs4all.nl> writes:
>
> > Thanks, I've got this to work in a test program, but I'm confused about
> > the code generated for xml.xsd. I used 'xsd cxx-tree --namespace-map
> > http://www.w3.org/XML/1998/namespace=XmlNamespace xml.xsd' and see that
> > the generated .cxx file does not contain any executable code, nor does
the
> > generated .hxx file declare anything in namespace XmlNamespace.  Instead
> > all code related to xml:base is in the files generated from my own .xsd
> > file.

For the source of this program, named 'explicit', see [3], on the left.

> xml.xsd defines four global attributes and an attribute group. Those are
> meant to be used via the ref="" attribute. As a result, there is nothing
> being generated for these constructs where they are defined (xml.xsd),
> only where they are used (your schema). XSD does not (yet) analyze the
> schema to detect such a (presumably rare) case where there is nothing
> useful being generated. So you still need to translate xml.xsd since
> there will be #include "xml.hxx" directives present in the code generated
> from your schema.

Just documenting the obvious: In this case, file xml.cxx can be
ignored, it does not need to be compiled, and file xml.o is not needed
by the linker.  One step beyond is not to use file xml.xsd at all, and
to create a dummy file xml.hxx.  This is demonstrated in file
Makefile.tricky for the program named 'explicit' mentioned above.

> > > If you want to allow say xml:base in all types in your schema then
> > > you may want to create a base type which includes only that attribute
> > > and then inherit all other types from it.
> >
> > Unfortunately, I need to be able to access xml:base in code generated
from
> > schemas I do not author, where the use of xml:base is covered by a
> > '<xs:anyAttribute namespace="##other"/>'.  So, instead of using a base
> > type in XML, I would need a base class in C++.  And unless I've missed
> > something, there is no way to tell xsd to generate its classes ': public
> > XmlNamespace' (for instance, where XmlNamespace is a class that
implements
> > access to xml:base.).
>
> There are a number of ways you can implement this (in the order of
> increasing sophistication):
>
>
> 1. Use DOM association. You can pass the xml_schema::flags::keep_dom flag
>    to one of the parsing functions which will result in the DOM nodes
>    corresponding to the tree nodes being accessible via the _node()
>    function. See Section 3.2, "Flags and Properties" of the C++/Tree
>    Mapping Manual[1] as well as 'mixed' example for more information.
>    Using the DOM API you can check for presence of the xml:base attribute.


I've got this to work.  See [3], the program named 'DOM_association' in
item 1 on the right.

Question: Shouldn't the Tree Mapping User Manual[4], in the paragraph
starting with "Keeping association with DOM nodes is useful for
dealing", explicitely mention that the use of the
xml_schema::flags::keep_dom flag requires the use of the flag
xml_schema::flags::dont_initialize as well?

Question: I thought I had to release whatever is returned from
DOMAttr::getValue(), but when I try this, it results in "*** glibc
detected *** double free or corruption (out): 0x080827f8 ***" at the
xercesc::XMLString::release().  Is the storage somehow released by
xml:transcode?

> 2. You can do pretty much what you've described above by customizing the
>    types that have <xs:anyAttribute namespace="##other"/> and check/extract
>    the xml:base attribute in the constructor. See the C++/Tree Mapping
>    Customization Guide[2] as well as the examples in the custom/ directory
>    for details.

Also gotten this to work.  See [3], the program named 'custom-types'
in item 2 on the right.

Unfortunately, but IMHO unavoidably, 'custom-types' still requires the
xml_schema::flags mentioned above.  Without them, the DOM is not
available during the execution of the bodies of the contructors of the
custom types.

> 3. This is a variation of (2), for cases where you have a lot of unrelated
>    types that all allow for <xs:anyAttribute namespace="##other"/>. In this
>    case you may want to customize the xml_schema::type class which
>    corresponds to XML Schema anyType and is a base for every generated
>    types. You can customize xml_schema::type by inheriting from the
>    original and checking for xml::base in the constructor. Again, see the
>    C++/Tree Mapping Customization Guide[2] and examples for details.
>
> [1]
http://www.codesynthesis.com/projects/xsd/documentation/cxx/tree/manual/#3.2
>
> [2] http://wiki.codesynthesis.com/Tree/Customization_guide

I'm not sure I understand what you are saying here, but it sounds like
making modifications to xsd's source.  As I'm not ready to do that
(yet, see below), I created a base class to handle the access to the
xml:base attribute instead (in files xml-base.*), and derived my
custom types from both the class generated by xsd and from this base
class.  See [3], the program named 'custom-xmlbase' in item 3 on the
right.

As expected, the driver logic in file custom-xmlbase.cpp is almost
identical to that in file explicit.cpp for program 'explicit'
mentioned at the top of this post.  The one notable difference is that
for simple types, but not for complex types, it is necessary to
qualify base() with xml_base:: (the name of my base class) to resolve
ambiguity.

Unfortunately, building this program fails with

g++ -g -Wall -W   xml-base.o custom-types.o driver.o test2.o  -lxerces-c
-o driver
xml-base.o: In function
`xsd::cxx::tree::traits<xsd::cxx::tree::uri<wchar_t,
xsd::cxx::tree::simple_type<xsd::cxx::tree::_type> >,
wchar_t>::create(xercesc_2_7::DOMAttr const&, xsd::cxx::tree::flags,
xsd::cxx::tree::_type*)':
/usr/include/xsd/cxx/tree/elements.hxx:735: undefined reference to
`xsd::cxx::tree::uri<wchar_t,
xsd::cxx::tree::simple_type<xsd::cxx::tree::_type>
>::uri(xercesc_2_7::DOMAttr const&, xsd::cxx::tree::flags,
xsd::cxx::tree::_type*)'
collect2: ld returned 1 exit status

File xml-base.cpp contains the following code fragment

        ::std::auto_ptr< base::type > r (
          base::traits::create (
            a.dom_attribute (),
            f | ::xml_schema::flags::not_root,
            &type));

which I presume is the cause of this problem.  As this code was copied
from code generated by xsd (from [3], on the left), and it seems that
the missing code is created in file driver.o in that case, but not
here, I'm a bit confused.

At the moment, the base class only implements the getters and the
setters for the xml:base attribute, and that only for chartype whar_t.
This is sufficient for my immediate needs, but I would like to see
options added to xsd to generate and use code for a full
implementation of the xml namespace, along the line you suggested, or
along the line I implemented it.  These options would be very similar
to the existing --generate-xml-schema and --extern-xml-schema
options. For instance '--generate-xml-namespace <schemafile>' would
generate the implementation, and '--with-xml-namespace <schemafile>
<type>' would instruct to use it for the type given.

I'm willing to try and implement this new feature in xsd.  Could you
point me to the source files where I would have to start this?

With kind regards,

Jeroen.

[3] http://www.xs4all.nl/~jnw/codesynthesis/xmlnamespace/index.html

[4] file:///usr/share/doc/xsd/cxx/tree/manual/index.xhtml#3.2 as
    installed by xsd_2.3.0-1_i386.deb.





More information about the xsd-users mailing list