Reputation: 898
I've inherited a project which uses JAXB heavily to map XML messages onto Java objects. The problem I have is that some of the data which I receive (in this case nested XML of unknown form) has NOT to be unmarshalled, rather captured as a String.
An example will help
<a>
<b></b>
<c></c>
<d>
<!-- "Unknown" XML here -->
<maybeE></maybeE>
<maybeF></maybeF>
<!-- etc etc -->
<d/>
</a>
So I would want the JAXB to unmarshall "b" and "c" but "d" it would capture the nested XML as a string i.e. not parsed.
So calling:
getD()
Would return string:
"<maybeE></maybeE><maybeF></maybeF>"
Upvotes: 4
Views: 4344
Reputation: 149007
You can keep unknown XML using the @XmlAnyElement
annotation. By default this will keep it as a DOM. If you want it stored in another format (such as String
) then you can specify a DomHandler
:
Full Example
Upvotes: 0
Reputation: 351
@Andrew B: Your code can even be improved:
public String getOperationsAsString() throws Exception{
StringWriter writer = new StringWriter();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
for (Node node: operations) {
transformer.transform(new DOMSource(node), new StreamResult(writer));
}
return writer.toString();
}
That way, you create the Transformer only once and you do not need the StringBuilder. StringWriter already writes into a StringBuffer internally.
Upvotes: 1
Reputation: 1668
I found the above very useful; I had a similar mapping issue where I had HTML which was not escaped or encoded stored in an xml file - and I wanted to map this to a String property.
I used the annotation:
@XmlElementWrapper(name="operations")
@XmlAnyElement
private List<Node> operations;
Then used a transformer to print the node tree:
public String getOperationsAsString() throws Exception{
StringBuilder builder = new StringBuilder();
for (Node node: operations) {
StringWriter writer = new StringWriter();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.transform(new DOMSource(node), new StreamResult(writer));
builder.append(writer.toString());
}
return builder.toString();
}
Upvotes: 1
Reputation: 403481
You can't capture the nested content as a String, but you can capture it as a DOM, e.g.
@XmlRootElement(name="a")
public class A {
@XmlElement
private String b;
@XmlElement
private String c;
@XmlAnyElement
private List<Element> content;
}
Whatever <a>
contains, which does not match <b>
or <c>
, will be stored under content
. You can then convert those Element
objects into Strings, if you so wish.
Upvotes: 4