2010-05-04 4 views
4

Je travaille sur une application client webservices et je l'ai surtout fonctionné. Je peux récupérer et lire des données provenant du service Web d'une tierce partie. Maintenant, je dois soumettre des données et je suis coincé.Objet Java aux éléments XML?

Les classes pour les objets que je récupère/soumets ont été générées à partir de fichiers XSD via l'outil xjc. La partie sur laquelle je suis coincé transforme un de ces objets en un arbre XML à soumettre au service web.

Lorsque je récupère/envoie une requête de/vers le ws, il contient un objet 'payload'. Il est défini dans le code Java (liste partielle):

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "PayloadType", propOrder = { 
    "compressed", 
    "document", 
    "any", 
    "format" 
}) 
public class PayloadType { 

    @XmlElement(name = "Compressed") 
    protected String compressed; 
    @XmlElement(name = "Document") 
    protected List<String> document; 
    @XmlAnyElement 
    protected List<Element> any; 
    protected String format; 

    public List<Element> getAny() { 
     if (any == null) { 
      any = new ArrayList<Element>(); 
     } 
     return this.any; 
    } 

} 

Le seul domaine qui me préoccupe est le champ « tout » qui contient un arbre XML. Quand je récupère des données du ws, j'ai lu ce champ avec quelque chose comme ceci: ('root' est de type org.w3c.dom.Element et est le résultat de l'appel 'getAny(). Get (0)' sur le objet de charge utile)

NodeList nl = root.getElementsByTagName("ns1:Process"); // "ns1:Process" is an XML node to do something with 
if (nl != null && nl.getLength() > 0) { 
    for (int i = 0; i < nl.getLength(); i++) { 
     Element proc = (Element) nl.item(i); 
     try { 
      // do something with the 'proc' Element here... 
     } catch (Exception ex) { 
      // handle problems here... 
     } 
    } 
} 

La soumission de données est l'endroit où je suis bloqué. Comment puis-je prendre un objet java créé à partir de l'une des classes générées à partir de XSD et le transformer en un objet Element que je peux ajouter à la liste «any» de l'objet de charge utile? Par exemple, si j'ai une classe DailyData et je crée et le remplir avec des données:

DailyData dData = new DailyData(); 
dData.setID = 34; 
dData.setValues = "3,5,76,23"; 

Comment puis-je ajouter cet objet « DData » à la « une » liste de l'objet de la charge utile? Cela doit être un élément. Est-ce que je fais quelque chose avec un marshaller de JAXBContext? J'ai utilisé cela pour vider l'objet 'dData' à l'écran pour vérifier la structure XML.

Je suis sûr que la réponse me regarde dans le visage mais je ne peux pas le voir!

Dave

MISE À JOUR: Got it travailler avec l'extrait de code ci-dessous:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
Document doc = dbf.newDocumentBuilder().newDocument(); 

JAXBContext context = JAXBContext.newInstance(DailyData.class); 
Marshaller marshaller = context.createMarshaller(); 
marshaller.marshal(dData, doc); 


PayloadType payload = new PayloadType(); 
payload.getAny().add((Element)doc.getFirstChild()); 
+0

I * pense * que je l'ai compris mais je Je ne saurai pas avec certitude jusqu'à ce que nous ayons des données de test dans notre environnement DEV Je posterai ma réponse si elle s'avère correcte – DaveKub

+0

Vous auriez dû répondre à votre propre question, parce que j'aurais voté :-) est le plus utile. – rds

Répondre

1

Le type de champ List<Element> est habituellement généré par XJC quand vous avez quelque chose comme ça dans le schéma:

<xs:any processContents="skip" maxOccurs="unbounded" minOccurs="0" /> 

La clé ici est processContents="skip", ce qui signifie «tout est permis» - tout XML bien formé peut y entrer. Parce que c'est un free-for-all, tout ce que XJC peut faire est de le représenter comme un DOM, et il devient de votre responsabilité de gérer cette charge utile.

Si vous supprimez processContents="skip", JAXB tentera de lier la charge utile à un modèle objet, s'il peut faire correspondre le contenu XML utile à une classe du JAXBContext. Dans ce cas, XJC génère un champ de type List<Object>.

Cela peut ne pas sembler une amélioration, mais ce List peut contenir Element (si le JAXBContext ne reconnaît pas la charge utile comme quelque chose qu'il peut se lier à), ou JAXBElement (si elle reconnaît qu'il). Ce dernier contient la version liée de la charge utile et est beaucoup plus facile à gérer.

Tout ceci est décrit plus en détail here.

Si vous ne pouvez pas modifier le schéma, et que vous êtes bloqué avec processContents="skip", vous devrez passer à travers les cerceaux. Vous pouvez construire une autre JAXBContext qui connaît vos classes de charge utile, et l'utiliser pour rassembler un Element (en utilisant quelque chose comme marshaller.marshal(payload, new DOMResult()). Vous pouvez ensuite vider cet élément dans la charge utile.

+0

Merci pour l'explication et je vais vérifier le lien. Puisque les fichiers XSD sont fournis par un tiers, je ne veux pas les changer. Alors, c'est le saut de cerceau! La façon dont je l'ai fait implique une organisation similaire à votre suggestion. Mon code s'exécute sans erreurs; le test sera de voir si 'leur' ​​webservice accepte ce que j'envoie, une fois que les données de test sont disponibles dans leur système ... – DaveKub

+1

J'ai commencé à travailler comme suggéré! J'ai mis mon code au bas de ma question initiale. – DaveKub

0

La première chose, tout type d'élément peut contenir XML à l'intérieur. La validation du schéma devrait donc fonctionner correctement même si vous y ajoutez une représentation XML de la classe DailyData.

Maintenant pour votre autre question sur la classe marshaling DailyData. Si cette classe était générée en utilisant le compilateur xjc lui-même, cette classe (ou une autre classe générée) connaîtrait déjà le moyen de convertir cet objet en XML.

Je ne l'ai pas utilisé directement, mais le lien ci-dessus vous aider à

http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/rwbs_xjc.html