Question

Using JAXB, is there a preferred (or best) way to take an XML fragment from a document and then include that fragment in another document? Mapping from one schema to another. Does anyone have a reference to that method? I have attempted to find some ways of doing this, but most search results resulted in just marshalling and unmarshalling.

I have multiple XML source documents that contains a XML fragments that I want to include in a secondary destination XML document. The destination fragment would look exactly the same as the source fragment. The namespaces are different for both source and destingation XML document mainly because the schemas were slightly different for the same tags, but the fragment was defined the same except that it was in the parent namespace (with JAXB object generation, I wanted package separation of the Java objects for each namespace, because elements were named the same for different data and had some issues trying to use a common schema for the fragment).

For a given source XML of MyDoc (see below), I have a subdoc XML fragment that I want to include in a list of subdocs in destination XML of DestDoc. Attrib_1 is named the same in the destination document, however the content types are different. I'm trying to take subdoc from MyDoc and include in a list of subdocs within DestDoc as shown below. Since the subdoc is the same XML, I just need to convert from mydoc/subdoc to destdoc/subdocs/subdoc.

Since I am starting with XML, I can unmarshall to MyDoc objects and get the subdoc object. At this point, I could marshall that out to an XML fragment, attempt to insert that into the destination XML parent elements at the right location, and then unmarshall as the destination object to add additional content or have a subdoc mapper to translate between mydoc/subdoc object and destdoc/subdoc object, but I would then have an object that depends on the two schemas. If either schema changes, it's a maintenance point. Ultimately, after all of the creational aspects of DestDoc, I will be marshalling out to XML for input to another process.

A common example I've found if the names MyDoc and DestDoc don't make sense, envision Bookstore as DestDoc, subdocs as books, subdoc as book, and MyDoc as BookInfo. Attrib_1 might be book_id with different values for source and destination while attrib_6 might be a summary count of subdocs.

Source XML:

<MyDoc xmlns="http://www.test.com/xsd/mydoc">
  <attrib_1>987</attrib_1>
  <attrib_2>bcd</attrib_2>
  <subdoc>
    <attrib_3>a1</attrib_3>
    <attrib_4>b1</attrib_4>
  </subdoc>
</MyDoc>

Destination XML:

<DestDoc xmlns="http://www.test.com/xsd/destdoc">
  <attrib_1>abc</attrib_1>
  <attrib_5>123</attrib_5>
  <attrib_6>456</attrib_6>
  <subdocs>
    <subdoc>
      <attrib_3>a1</attrib_3>
      <attrib_4>b1</attrib_4>
    </subdoc>
  </subdocs>
</DestDoc>
Was it helpful?

Solution 2

With the additional requirements specified in your comments on Daniel Kec's answer, you're probably best off using this approach:

  1. Unmarshal the old data into an object instance of it's particular type (as defined in the old schema.)
  2. Create an empty object instance of the new type you're creating under the new schema.
  3. Populate the fields of the new object with whatever corresponding fields you want from the old-data object, as well as whatever new data you prefer.
  4. Marshal out the new data using a validator defined by the new schema.

As an alternative, you could define a class that implements the interface specified by the new schema, and which encapsulates an instance of the old type to which particular method implementations are delegated. You'd then (presumably) pass the older-type object (after it's been unmarshalled) as an argument to the constructor of the class in question. You could then marshal out the instance of the new class.

OTHER TIPS

Try marshaling to a DOM:

   DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
   dbf.setNamespaceAware(true);
   DocumentBuilder db = dbf.newDocumentBuilder();
   Document doc = db.newDocument();

   m.marshal(jaxbElement, doc);

And then use just old fashioned adopt node.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top