Home  >  Article  >  jaxb unmarshalling by declaring types does not work when there is no namespace

jaxb unmarshalling by declaring types does not work when there is no namespace

PHPz
PHPzforward
2024-02-06 09:09:09824browse
Question content

I am building a parser for vast documents, which are xml documents, there is an official xsd, there are several versions: https://github.com/interactiveadvertisingbureau/ vast/tree/master

I needed to be able to unmarshal the incoming xml, so I generated the model using jaxb2-maven-plugin.

I need to be able to handle incoming xml, which may or may not mention namespaces: my problem is that it works when there is a namespace, but not when there is no namespace.

As per https://stackoverflow.com/a/8717287/3067542 and https://docs.oracle.com/javase/6/docs/api/javax/xml/bind/unmarshaller.html#unmarshalbydeclaredtype, I understand There is a workaround because I know the target class type so I can force unmarshalling to that class regardless of namespace or not.

This is my code (also available on github)

JAXBContext jc = JAXBContext.newInstance(VAST.class);
Unmarshaller u = jc.createUnmarshaller();

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);

DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader(xmlString)));
JAXBElement<VAST> foo = u.unmarshal( doc, VAST.class);

return new CustomVast(foo.getValue());

When running the test, I found that the inner class was not populated:

Did I miss something? Is there an additional flag that needs to be set when generating classes using jaxb2-maven-plugin so that it can work?


Correct answer


This answer is obviously not optimized, but will give you a hint on how to make it work on version 4.2 of namespace and non-namespace xml:

Here is the body method of parsexml

jaxbcontext jc = jaxbcontext.newinstance(vast.class);
unmarshaller u = jc.createunmarshaller();

// should be optimized
transformerfactory tf = transformerfactory.newinstance();
stringwriter sw = new stringwriter();
url urlxslt = vastparser.class.getclassloader().getresource("xslt/vast_4.2.xslt");
file filexslt = new file(urlxslt.touri());
transformer t = tf.newtransformer(new streamsource(new fileinputstream(filexslt)));
// transform original xml with xslt to always add the namespace in the parsing 
t.transform(new streamsource(new stringreader(xmlstring)), new streamresult(sw));

// unmarshall transformed xml
jaxbelement<vast> foo = u.unmarshal(new streamsource(new stringreader(sw.tostring())), vast.class);

return new customvast(foo.getvalue());

src/main/resources/xslt/vast_4.2.xslt is:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|text()|comment()|processing-instruction()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- adds the xmlns part to the VAST element -->
    <xsl:template match="/VAST">
        <VAST xmlns="http://www.iab.com/VAST">
            <xsl:apply-templates select="@*|node()"/>
        </VAST>
    </xsl:template>

    <xsl:template match="*">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

At this point, both unit tests apply to Section 4.2.

The above is the detailed content of jaxb unmarshalling by declaring types does not work when there is no namespace. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete