JAXB partielle unmarshalling Éléments sans @XMLRootElement
Je suis en utilisant le partielle unmarshalling exemple de JAXB, mais je suis incapable de unmarshal XML-Éléments qui ne sont pas sur le niveau de la racine (la cause qu'ils n'ont pas de @XmlRootElement tag). Dans mon exemple, j'ai essayé de lire le shipTo-Élément au lieu de purchaseOrder-Élément.
Normalement, je devrais travailler avec JAXBElement unmarshal(Source de source de,la Classe declaredType), mais comme l'exemple à l'aide d'un UnmarshallerHandler et un XMLFilterImpl je ne sais pas où en parler Jaxb la Classe qu'il doit utiliser.
Mon message d'erreur est: Causée par: javax.xml.bind.UnmarshalException: inattendu élément (uri:"", locale:"shipTo"). Éléments attendus sont <{}commentaire>,<{}purchaseOrder>,<{}purchaseOrders>
J'ai googlé autour d'un lot, mais n'ai rien trouvé d'utile encore.
Voici l'exemple de code à partir de la JaxB-site web:
Main.java
public class Main {
public static void main( String[] args ) throws Exception {
//create JAXBContext for the primer.xsd
JAXBContext context = JAXBContext.newInstance("primer");
//create a new XML parser
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
XMLReader reader = factory.newSAXParser().getXMLReader();
//prepare a Splitter
Splitter splitter = new Splitter(context);
//connect two components
reader.setContentHandler(splitter);
for( int i=0; i<args.length; i++ ) {
//parse all the documents specified via the command line.
//note that XMLReader expects an URL, not a file name.
//so we need conversion.
reader.parse(new File(args[i]).toURL().toExternalForm());
}
}
}
Splitter.java
public class Splitter extends XMLFilterImpl {
public Splitter( JAXBContext context ) {
this.context = context;
}
/**
* We will create unmarshallers from this context.
*/
private final JAXBContext context;
public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
throws SAXException {
if( depth!= 0 ) {
//we are in the middle of forwarding events.
//continue to do so.
depth++;
super.startElement(namespaceURI, localName, qName, atts);
return;
}
if( namespaceURI.equals("") && localName.equals("purchaseOrder") ) {
//start a new unmarshaller
Unmarshaller unmarshaller;
try {
unmarshaller = context.createUnmarshaller();
} catch( JAXBException e ) {
//there's no way to recover from this error.
//we will abort the processing.
throw new SAXException(e);
}
unmarshallerHandler = unmarshaller.getUnmarshallerHandler();
//set it as the content handler so that it will receive
//SAX events from now on.
setContentHandler(unmarshallerHandler);
//fire SAX events to emulate the start of a new document.
unmarshallerHandler.startDocument();
unmarshallerHandler.setDocumentLocator(locator);
Enumeration e = namespaces.getPrefixes();
while( e.hasMoreElements() ) {
String prefix = (String)e.nextElement();
String uri = namespaces.getURI(prefix);
unmarshallerHandler.startPrefixMapping(prefix,uri);
}
String defaultURI = namespaces.getURI("");
if( defaultURI!=null )
unmarshallerHandler.startPrefixMapping("",defaultURI);
super.startElement(namespaceURI, localName, qName, atts);
//count the depth of elements and we will know when to stop.
depth=1;
}
}
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
//forward this event
super.endElement(namespaceURI, localName, qName);
if( depth!=0 ) {
depth--;
if( depth==0 ) {
//just finished sending one chunk.
//emulate the end of a document.
Enumeration e = namespaces.getPrefixes();
while( e.hasMoreElements() ) {
String prefix = (String)e.nextElement();
unmarshallerHandler.endPrefixMapping(prefix);
}
String defaultURI = namespaces.getURI("");
if( defaultURI!=null )
unmarshallerHandler.endPrefixMapping("");
unmarshallerHandler.endDocument();
//stop forwarding events by setting a dummy handler.
//XMLFilter doesn't accept null, so we have to give it something,
//hence a DefaultHandler, which does nothing.
setContentHandler(new DefaultHandler());
//then retrieve the fully unmarshalled object
try {
JAXBElement<PurchaseOrderType> result =
(JAXBElement<PurchaseOrderType>)unmarshallerHandler.getResult();
//process this new purchase order
process(result.getValue());
} catch( JAXBException je ) {
//error was found during the unmarshalling.
//you can either abort the processing by throwing a SAXException,
//or you can continue processing by returning from this method.
System.err.println("unable to process an order at line "+
locator.getLineNumber() );
return;
}
unmarshallerHandler = null;
}
}
}
public void process( PurchaseOrderType order ) {
System.out.println("this order will be shipped to "
+ order.getShipTo().getName() );
}
/**
* Remembers the depth of the elements as we forward
* SAX events to a JAXB unmarshaller.
*/
private int depth;
/**
* Reference to the unmarshaller which is unmarshalling
* an object.
*/
private UnmarshallerHandler unmarshallerHandler;
/**
* Keeps a reference to the locator object so that we can later
* pass it to a JAXB unmarshaller.
*/
private Locator locator;
public void setDocumentLocator(Locator locator) {
super.setDocumentLocator(locator);
this.locator = locator;
}
/**
* Used to keep track of in-scope namespace bindings.
*
* For JAXB unmarshaller to correctly unmarshal documents, it needs
* to know all the effective namespace declarations.
*/
private NamespaceSupport namespaces = new NamespaceSupport();
public void startPrefixMapping(String prefix, String uri) throws SAXException {
namespaces.pushContext();
namespaces.declarePrefix(prefix,uri);
super.startPrefixMapping(prefix, uri);
}
public void endPrefixMapping(String prefix) throws SAXException {
namespaces.popContext();
super.endPrefixMapping(prefix);
}
}
Apprêt.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
<xsd:documentation xml:lang="en">
Purchase order schema for Example.com.
Copyright 2000 Example.com. All rights reserved.
</xsd:documentation>
</xsd:annotation>
<xsd:element name="purchaseOrders">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="purchaseOrder" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="purchaseOrder" type="PurchaseOrderType"/>
<xsd:element name="comment" type="xsd:string"/>
<xsd:complexType name="PurchaseOrderType">
<xsd:sequence>
<xsd:element name="shipTo" type="USAddress"/>
<xsd:element name="billTo" type="USAddress"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="items" type="Items"/>
</xsd:sequence>
<xsd:attribute name="orderDate" type="xsd:date"/>
</xsd:complexType>
<xsd:complexType name="USAddress">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="state" type="xsd:string"/>
<xsd:element name="zip" type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="country" type="xsd:NMTOKEN"
fixed="US"/>
</xsd:complexType>
<xsd:complexType name="Items">
<xsd:sequence>
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="productName" type="xsd:string"/>
<xsd:element name="quantity">
<xsd:simpleType>
<xsd:restriction base="xsd:positiveInteger">
<xsd:maxExclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="USPrice" type="xsd:decimal"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="shipDate" type="xsd:date" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="partNum" type="SKU" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<!-- Stock Keeping Unit, a code for identifying products -->
<xsd:simpleType name="SKU">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
test.xml
<purchaseOrders>
<!-- 1st -->
<purchaseOrder orderDate="1999-10-20">
<shipTo country="US">
<name>Alice Smith</name>
<street>123 Maple Street</street>
<city>Cambridge</city>
<state>MA</state>
<zip>12345</zip>
</shipTo>
<billTo country="US">
<name>Robert Smith</name>
<street>8 Oak Avenue</street>
<city>Cambridge</city>
<state>MA</state>
<zip>12345</zip>
</billTo>
<items/>
</purchaseOrder>
</purchaseOrders>
Oui, bon! Le code fonctionne, mais si vous modifiez cette façon qu'il faut lire "shipTo" au lieu de "purchaseOrder" l'erreur est à venir
OriginalL'auteur cloudnaut | 2011-06-26
Vous devez vous connecter pour publier un commentaire.
J'ai eu ce problème; en essayant d'utiliser partielle unmarshalling exemple de la jaxb l'implémentation de référence.
La solution, j'ai installé sur un fait d'ajouter des com.soleil.xml.bind.l'api.ClassResolver dans le unmarshaller créée dans la méthode startElement, ci-dessus. Voir:
Voici une maquette de résolution...
OriginalL'auteur user203289
Votre échantillon est trop compliqué (> 300 lignes). S'il vous plaît, pouvez-vous essayer de le rendre adapté à 30 lignes de code?
Dans la pratique, JAXB peut unmarshal un ruisseau avec 2 lignes de code (en supposant que vos classes sont correctement annoté):
Voir cet exemple complet (avec tests) pour plus d'.
Et cet article pour encore plus sur le sujet.
OriginalL'auteur yves amsellem
Vous pourriez tirer parti d'un
SAXSource
pour obtenir le comportement que vous recherchez:Exemple Complet:
OriginalL'auteur Blaise Doughan
Généralement cette erreur est renvoyée lorsque vous essayez de passer de l'élément enfant de la classe comme argument pour jaxb instance. essayer de passer de la racine de la classe comme argument et de vérifier si cela fonctionne ou pas
OriginalL'auteur anup r
C'est la fonction que j'utilise pour de tels cas.
Vous pouvez le mettre dans votre statique
Utils
classe.OriginalL'auteur EliuX