2009-11-17 3 views
4

Je travaille avec LMS eBay (Large Services marchands) et rencontrais l'erreur:Comment ajouter un attribut d'espace de noms à un élément dans JAXB lors du marshaling?

org.xml.sax.SAXException: SimpleDeserializer encountered a child element, which is NOT expected, in something it was trying to deserialize.

Après beaucoup d'essais et d'erreurs que je traçais le problème vers le bas. Il se trouve que cela fonctionne:

<?xml version="1.0" encoding="UTF-8"?> 
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents"> 
    <Header> 
    <Version>583</Version> 
    <SiteID>0</SiteID> 
    </Header> 
    <AddFixedPriceItemRequest xmlns="urn:ebay:apis:eBLBaseComponents"> 

alors que ce (ce que j'ai envoyais) n'a pas:

<?xml version="1.0" encoding="UTF-8"?> 
<BulkDataExchangeRequests xmlns="urn:ebay:apis:eBLBaseComponents"> 
    <Header> 
    <Version>583</Version> 
    <SiteID>0</SiteID> 
    </Header> 
    <AddFixedPriceItemRequest> 

La différence est l'attribut xml namespace sur le AddFixedPriceItemRequest. Tout mon XML est actuellement en cours de compilation via JAXB et je ne suis pas sûr de la meilleure façon d'ajouter un deuxième attribut xmlns à un élément différent dans mon fichier.

Voilà donc la question. Comment ajouter un attribut xmlns à un autre élément dans JAXB?

MISE À JOUR:

package ebay.apis.eblbasecomponents; 

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlType; 

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "AddFixedPriceItemRequestType", propOrder = { 
    "item" 
}) 
public class AddFixedPriceItemRequestType 
    extends AbstractRequestType 
{ 

    @XmlElement(name = "Item") 
    protected ItemType item; 

    public ItemType getItem() { 
     return item; 
    } 

    public void setItem(ItemType value) { 
     this.item = value; 
    } 
} 

Ajouté définition de classe demande.

MISE À JOUR 2: Sous la direction de la classe ci-dessus comme pour ainsi aucun effet:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(namespace = "urn:ebay:apis:eBLBaseComponents", 
name = "AddFixedPriceItemRequestType", propOrder = { 
    "item" 
}) 
public class AddFixedPriceItemRequestType 

MISE À JOUR 3: Voici un extrait de la classe BulkDataExchangeRequestsType. J'ai essayé de lancer un namespace="urn:ebay:apis:eBLBaseComponents" dans le @XmlElement pour AddFixedPriceItemRequest mais il n'a rien fait.

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "BulkDataExchangeRequestsType", propOrder = { 
    "header", 
    "addFixedPriceItemRequest" 
}) 
public class BulkDataExchangeRequestsType { 

    @XmlElement(name = "Header") 
    protected MerchantDataRequestHeaderType header; 
    @XmlElement(name = "AddFixedPriceItemRequest") 
    protected List<AddFixedPriceItemRequestType> addFixedPriceItemRequest; 

MISE À JOUR 4: Voici le morceau hideux de code qui est mise à jour le xml après marshalling pour moi. Cela fonctionne actuellement même si je n'en suis pas particulièrement fier.

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    dbf.setNamespaceAware(true); 
    DocumentBuilder db = dbf.newDocumentBuilder(); 
    Document doc = db.newDocument(); 
    marshaller.marshal(request, doc); 
    NodeList nodes = doc.getChildNodes(); 
    nodes = nodes.item(0).getChildNodes(); 
    for(int i = 0; i < nodes.getLength(); i++){ 
     Node node = nodes.item(i); 
     if (!node.getNodeName().equals("Header")){ 
      ((Element)node).setAttribute("xmlns", "urn:ebay:apis:eBLBaseComponents"); 
     } 
    } 

Merci pour toute l'aide à tous.

+0

Que voulez-vous dire par "généré via JAXB"? Pourriez-vous ajouter une définition de votre classe AddFixedPriceItemRequest? –

+0

J'utilise le marshaling via JAXB pour générer le XML. Je ne vois pas de balise spécifique qui ajoute l'attribut xmlns à la classe BulkDataExchangeRequestsType. J'ai ajouté la définition de classe AddFixedPriceItemRequestType à la question. –

+0

Pourquoi ne pas générer le schéma spécifié dans le WSDL? http://developer.ebay.com/webservices/bulk-data-exchange/latest/BulkDataExchangeService.wsdl –

Répondre

5

Pour autant que je peux dire, votre Les fragments XML sont sémantiquement identiques. L'attribut xmlns sur l'élément AddFixedPriceItemRequest est redondant, car il hérite implicitement de l'espace de nom de son élément parent. JAXB le sait, et ne prend donc pas la peine d'ajouter l'espace de noms à AddFixedPriceItemRequest - ce n'est tout simplement pas nécessaire.

Si le serveur ebay ne fonctionne que lorsque le AddFixedPriceItemRequestxmlns est présent, alors il est cassé, et demande des entrées supérieures à celles requises par XML et par le schéma. Si c'est effectivement le cas (ce qui est difficile à croire, mais possible), alors utiliser un modèle de document Java XML comme JAXB va être un combat, car cela supposera XML est XML est XML. Les informations de bas niveau sur lesquelles les éléments obtiennent les déclarations xmlns ne sont pas exposées à l'API, car elles ne devraient pas être nécessaires.

Rien de tout cela ne vous aide. Mon approche serait de marshal le modèle JAXB à un objet DOM (en utilisant un DOMResult passé à la Marshaller), puis voir si vous pouvez faire une modification manuelle du DOM pour forcer le xmlns dans le document aux endroits appropriés. Vous pouvez ensuite sérialiser ce DOM en XML et l'envoyer.

Vous ne devriez pas avoir à faire cela, et je soupçonne que vous faites peut-être quelque chose d'anormal quelque part; C'est plus probable que le service Web ebay étant cassé comme ça.


edit: voici une autre suggestion, un peu moins horrible que la solution JAXB-to-DOM-to-XML. Si votre requête XML est de structure statique raisonnable, avec uniquement les valeurs numériques/chaîne changeantes, définissez-la comme un modèle String, puis remplacez les valeurs lors de l'exécution et envoyez-la. Vous pouvez ensuite interpréter les résultats en utilisant JAXB. Je l'ai fait dans l'oast avec les services web que thyat a exigé des préfixes d'espace de noms très précis, quand persuader les bibliothèques de Java de se conformer à cela était déraisonnablement dur.

+0

Vous avez raison, cela n'a aucun sens, cependant, je l'ai testé - en envoyant exactement le même fichier (leur service LMS vous oblige à télécharger un fichier qu'ils traitent ensuite quand ils s'y retrouvent), sauf pour ce changement d'un xmlns supplémentaire. Sans cela, le service retourne "Échec" à chaque fois. Quand il est là, il n'a pas ce problème. Je suppose que j'espérais qu'il y avait un moyen plus facile - le faire glisser à travers DOM semble vraiment lourd, mais j'ai l'impression que toute solution sera une bête à ce stade. –

+0

voir edit pour une alternative – skaffman

+0

Malheureusement cela ne fonctionnera probablement pas car il est plutôt dynamique dans la façon dont il crée son contenu. Bonne pensée cependant, ce n'était pas le cas. –

3

Essayez d'utiliser l'annotation de classe

@XmlType(namespace="urn:ebay:apis:eBLBaseComponents") 

ou

@XmlElement(namespace="urn:ebay:apis:eBLBaseComponents") 

annotation de la propriété si vous ne souhaitez que spécifier l'espace de noms que dans certains certains cas

3

Vérifiez si les annotations @XmlElement manquent dans les champs générés et si l'attribut espace de noms est manquant. Ces deux doivent être présents afin d'obtenir le préfixe d'espace de noms pour chaque élément de votre xml marshalé.

Questions connexes