Saya sedang membina parser untuk dokumen yang luas, iaitu dokumen xml, ada xsd rasmi, terdapat beberapa versi: https://github.com/interactiveadvertisingbureau/vast/tree/master
Saya perlu dapat unmarshal xml masuk, jadi saya menjana model menggunakan jaxb2-maven-plugin
.
Saya perlu dapat mengendalikan xml masuk, yang mungkin atau mungkin tidak menyebut ruang nama: Masalah saya ialah ia berfungsi apabila terdapat ruang nama, tetapi bukan apabila tiada ruang nama.
Mengikuti https://stackoverflow.com/a/8717287/3067542 dan https://docs.oracle.com/javase/6/docs/api/javax/xml/bind/unmarshaller.html#unmarshalbydeclaredtype, saya faham ada Penyelesaian, kerana saya tahu jenis kelas sasaran, saya boleh memaksa unmarshalling ke kelas itu, ruang nama atau tidak.
Ini kod saya (juga tersedia di 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());
Semasa menjalankan ujian, saya mendapati kelas dalaman tidak diisi:
Adakah saya terlepas sesuatu? Adakah terdapat bendera tambahan yang perlu ditetapkan semasa menjana kelas menggunakan jaxb2-maven-plugin
supaya ia boleh berfungsi?
Jawapan ini jelas sekali tidak dioptimumkan, tetapi akan memberi anda petunjuk tentang cara menjadikannya berfungsi pada versi 4.2 ruang nama dan bukan ruang nama xml:
Berikut adalah kaedah badan 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
ialah:
<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>
Pada ketika ini, kedua-dua ujian unit boleh digunakan untuk bahagian 4.2.
Atas ialah kandungan terperinci jaxb unmarshalling dengan mengisytiharkan jenis tidak berfungsi apabila tiada ruang nama. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!