Search code examples
c++xmlcodesynthesis

CodeSynthesis XSD tree serialization on the fly


I'm using CodeSynthesis XSD tool to generate XML file according to a given XSD file. I know that it's possible to build an XML tree and serialize it to a stream. But my question is:

Is it possible to generate the XML elements one by one?

Suppose I want to generate a <root> element which contains <element1> and <element2>. Now I can only build the <root> tree and serialize it in one piece. What I want is:

First generate <root>, then <element1>...</element1> and <element2>...</element2>, finally </root>.

Because the parser support callbacks, it's easy to take control of each node immediately after the node is available. Is it possible for tree mapping also?

I dig the documentation but didn't found a proper answer. I'll appreciate any possible help or clues. Thanks in advance :)

--- Edit ---

To make it clear - First, the source XML data are generated by my program (not from existing XML file); Second, I want to serialize the XML object immediately after it is produced, instead of serializing a whole tree.

I know XSD/Tree targets on in-memory tree-like processing, but I wonder if it's possible to write like xxx_open and xxx_close etc.

Thanks again.


Solution

  • Yes, it is possible to generate the elements one by one with CodeSynthesis XSD. For instance, this streaming example generates this XML file:

    <?xml version="1.0" encoding="UTF-8" standalone="no" ?>
    <op:object xmlns:op="http://www.codesynthesis.com/op" id="123" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.codesynthesis.com/op position.xsd">
      <header>
        <name>Lion's Head</name>
        <type>rock</type>
      </header>
      <position lat="-33.8569" lon="18.5083"/>
      <position lat="-33.8568" lon="18.5083"/>
      <position lat="-33.8568" lon="18.5082"/>
      <position lat="-33.857" lon="18.5083"/>
      <position lat="-33.8569" lon="18.5084"/>
      <position lat="-33.857" lon="18.5084"/>
      <position lat="-33.857" lon="18.5082"/>
      <position lat="-33.8569" lon="18.5082"/>
    </op:object>
    

    In the file driver.cxx each position element is generated by calling

    s.next ("position", pos);
    

    To have more control over what namespace prefixes will be used in the output, you could use this function instead from the file serializer.hxx

    // Serialize next object model fragment into an element with the specified
    // namespace and qualified name as well as namespace declarations.
    //
    template <typename T>
    void
    next (const std::string& ns,
          const std::string& name,
          const namespace_infomap&,
          const T& x);
    

    In the file driver.cxx the position object is being created out of a XML DOM tree

    position pos (*doc1->getDocumentElement ());
    

    so it is this constructor that is being used:

    position (const ::xercesc::DOMElement& e,
              ::xml_schema::flags f = 0,
              ::xml_schema::container* c = 0);
    

    that can be seen in the generated file position.hxx.

    But you mention that you are creating your objects out of a non-XML source, so you would instead need to use the constructor that takes the member values as input:

    position (const lat_type&,
              const lon_type&);