2016-06-11 30 views
1

Ich bin neu in Rest API. Ich habe eine XML-Ausgabe, die ich entpacken muss. Unten ist die XML-Ausgabe:So entpacken Sie diese Art von XML in Java

<dsml> 
    <entries> 
     <entry dn="uid=7686,c=in,ou=pages,o=example.com"> 
      <att name="uid"> 
       <value>7568766</value> 
      </att> 
      <att name="email"> 
       <value>[email protected]</value> 
      </att> 
      <att name="callname"> 
       <value>John</value> 
      </att> 
     </entry> 
     <entry dn="uid=7689,c=in,ou=pages,o=example.com"> 
      <att name="uid"> 
       <value>7678766</value> 
      </att> 
      <att name="callname"> 
       <value>Mike</value> 
      </att> 
     </entry> 
     <entry dn="uid=7690,c=in,ou=pages,o=example.com"> 
      <att name="uid"> 
       <value>75858766</value> 
      </att> 
      <att name="email"> 
       <value>[email protected]</value> 
      </att> 
      <att name="callname"> 
       <value>rahul</value> 
      </att> 
     </entry> 
    </entries> 
</dsml> 

Die tatsächliche XML-Ausgabe hat insgesamt 37 Einträge. Unten ist die Modellklasse:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "user") 
public class User implements Serializable{ 
    private static final long serialVersionUID = 1L; 

    @XmlElement(name = "uid") 
    private int uid; 

    @XmlElement(name = "callname") 
    private String callname; 

    @XmlElement(name = "email") 
    private String email; 

    public int getId() { 
     return uid; 
    } 
    public void setId(int uid) { 
     this.uid = uid; 
    } 
    public String getFirstName() { 
     return callname; 
    } 
    public void setFirstName(String callname) { 
     this.callname = callname; 
    } 
    public String getmail() { 
     return email; 
    } 
    public void setmail(String email) { 
     this.email = email; 
    } 
} 

Unten ist die Ruhe Api Klassencode:

public class UsingRestAPI { 
    public static void main(String[] args) 
    { 
     try 
     { 
      URL url = new URL("www.example.com"); 
      HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 
      conn.setRequestMethod("GET"); 
      conn.setRequestProperty("Accept", "application/xml"); 

      if (conn.getResponseCode() != 200) 
      { 
       throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode()); 
      } 

      BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream()))); 
      String apioutput="",temp=""; 
      while ((apioutput = br.readLine()) != null) { 
       temp += apioutput; 
       System.out.println(apioutput); 
      } 


      JAXBContext jaxbContext = JAXBContext.newInstance(User.class); 
      Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
      User user = (User) jaxbUnmarshaller.unmarshal(new StringReader(temp)); 

      System.out.println(user.getId()); 
      System.out.println(user.getFirstName()); 
      System.out.println(user.getmail()); 

     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } catch (JAXBException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Während dieser Code ausgeführt wird, erhalte ich Fehler

javax.xml.bind.UnmarshalException - mit verknüpfter Ausnahme: [org.xml.sax.SAXParseException; Zeilennummer: 1; Spaltennummer: 110; Externe DTD: Fehler beim Lesen der externen DTD 'dsml.dtd', da 'http' aufgrund der Einschränkung durch die Eigenschaft 'accessExternalDTD' nicht zulässig ist.]

Ich habe versucht, indem ich die Eigenschaft ACCESS_EXTERNAL_DTD auf true änderte, aber es gab ein weiterer Fehler:

javax.xml.bind.PropertyException: name: http://javax.xml.XMLConstants/property/accessExternalDTD value: true 
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.setProperty(Unknown Source) 
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.setProperty(Unknown Source) 
    at UsingRestAPI.main(UsingRestAPI.java:60) 

Antwort

0

(bearbeitet Antwort: Userclass und DsmlFactory getEntities() -Methode bearbeitet)

ich denke, es ist wegen der Unterschied Ihrer XML-Struktur und Ihre Klasse-Struktur ist. Ich würde nie Elemente verwenden, die denselben Namen aber unterschiedliche Werttypen haben (wie Ihre att und value Elemente). Warum? Es ist kein Problem für den Marshaller, es ist ein Problem für den Unmarshaller. Weil, wie ich weiß, es den Typ eines untergeordneten Elementwerts basierend auf dem name-Attribut des übergeordneten Elements nicht definieren kann. Auch wenn Sie statische innere Klassen von generischem Typ definieren (zB interface Attribute<V> und static class Uid<Integer>, static class Email<String> und was auch immer, werden Sie Ihre Arbeit nur noch komplizierter machen.

Aber wenn Sie schreibt @XmlElement(name="att") Set<Attribute> attributes, wo das Attribut Zählung nicht wichtig für die Marshaller ist, und der Unmarshaller auch, es ist etwas anderes.

Aber um es einfach zu halten, würde ich wirklich die Struktur empfehlen <email>{value}</email>, , etc.

ich eine einfache Xml Marshaller/Unmarshaller (ohne REST) ​​zu testen gemacht haben, das funktioniert:

Meine Dslm Xml Wurzelklasse:

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class Dsml { 

    @XmlElement 
    private Entities entities; 

    public Dsml() {} 
    public Dsml(Entities entities) { 
     this.entities = entities; 
    } 

    public Entities getEntities() { 
     return entities; 
    } 

    public void print() { 
     entities.print(); 
    } 
} 

Meine Entities Klasse:

@XmlAccessorType(XmlAccessType.FIELD) 
public class Entities { 
    @XmlElement(name = "entity") 
    private Set<User> users = new LinkedHashSet<>(); 

    public Entities() {} 

    public Entities(Set<User> users) { 
     this.users = users; 
    } 

    public Set<User> getUsers() { 
     return Collections.unmodifiableSet(users); 
    } 

    public void print() { 
     if (users != null && !users.isEmpty()) { 
      users.stream().forEach(User::print); 
     } else { 
      System.out.println("No entities found"); 
     } 
    } 
} 

Meine User Klasse:

@XmlAccessorType(XmlAccessType.FIELD) 
public class User { 

    @XmlAttribute 
    private String dn; 

    @XmlElement 
    private int uid; 

    @XmlElement 
    private String email; 

    @XmlElement 
    private String callname; 


    public User() {} 

    public User(int uid, String dn, String email, String callname) { 
     setUid(uid); 
     setEmail(email); 
     setCallname(callname); 
     setDn(dn); 
    } 

    public int getUid() { 
     return uid; 
    } 

    public void setUid(int uid) { 
     this.uid = uid; 
    } 

    public String getEmail() { 
     return email; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 

    public String getCallname() { 
     return callname; 
    } 

    public void setCallname(String callname) { 
     this.callname = callname; 
    } 

    public String getDn() { 
     return dn; 
    } 

    public void setDn(String dn) { 
     this.dn = dn; 
    } 

    public void print() { 
     System.out.println("Dn: " + dn); 
     System.out.println("Uid: " + uid); 
     System.out.println("Email: " + email); 
     System.out.println("Callname: " + callname); 
    } 
} 

Meine DsmlFactory Marshaller/Unmarshaller Test-Klasse (sicher sein, Sie haben D:\ Partition und Sie haben Lesen | Readwrite Rechte auf sie oder anderen Pfad eingeben innerhalb von Methoden saveXml() und readAndPrint():

public final class DsmlFactory { 
    private DsmlFactory() {} 
    public static Entities getEntities() { 
     Set<User> users = new LinkedHashSet<>(); 
     users.add(new User(1000, "dn1", "email1", "callname1")); 
     users.add(new User(2000, "dn2", "email2", "callname2")); 
     users.add(new User(3000, "dn3", "email3", "callname3")); 
     users.add(new User(4000, "dn4", "email4", "callname4")); 
     users.add(new User(5000, "dn5", "email5", "callname5")); 
     return new Entities(users); 
    } 

    public static void saveXmlTest() { 
     try { 
      File file = new File("D:/test.xml"); 
      if (!file.exists()) { 
       try { 
        file.createNewFile(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 

      JAXBContext jaxbContext = JAXBContext.newInstance(Dsml.class); 
      Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); 

      jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
      Dsml dsml = new Dsml(getEntities()); 
      jaxbMarshaller.marshal(dsml, file); 
      jaxbMarshaller.marshal(dsml, System.out); 

     } catch (JAXBException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void readAndPrintXml() { 
     JAXBContext jaxbContext; 
     try { 
      jaxbContext = JAXBContext.newInstance(Dsml.class); 
      Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 

      Dsml dsml = (Dsml) jaxbUnmarshaller.unmarshal(new File("D:/test.xml")); 
      dsml.print(); 
     } catch (JAXBException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void testIt() { 
     saveXmlTest(); 
     readAndPrintXml(); 
    } 
} 

Und mein main TestDr ive:

public class Main { 
    public static void main(String[] args) { 
     DsmlFactory.testIt(); 
    } 
} 
0

Darf ich Ihnen vorschlagen folgendes versuchen:

Schritt 1: Erstellen Sie eine Klasse mit dem Namen Attribute wie folgt:

Attribute.java

import java.io.Serializable; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElement; 

public class Attribute implements Serializable { 
private static final long serialVersionUID = 1L; 
private String name; 
private String value; 
public Attribute() { 
} 
public Attribute(String name, String value) { 
    this.name = name; 
    this.value = value; 
} 
@XmlAttribute 
public String getName() { 
    return name; 
} 
public void setName(String name) { 
    this.name = name; 
} 
@XmlElement 
public String getValue() { 
    return value; 
} 
public void setValue(String value) { 
    this.value = value; 
} 
} 

Schritt 2: Bitte ändern Sie Ihre Klasse Student wie folgt:

Student.java

import java.io.Serializable; 
import java.util.List; 
import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElement; 

public class Student implements Serializable { 
private static final long serialVersionUID = 1L; 
private List<Attribute> attributes; 
private String distinguishedName; 
public Student() { 
} 
public Student(String distinguishedName, List<Attribute> attributes) { 
    this.distinguishedName = distinguishedName; 
    this.attributes = attributes; 
} 
@XmlAttribute(name = "dn") 
public String getDistinguishedName() { 
    return distinguishedName; 
} 
public void setDistinguishedName(String distinguishedName) { 
    this.distinguishedName = distinguishedName; 
} 
@XmlElement(name = "att", type = Attribute.class) 
public List<Attribute> getAttributes() { 
    return attributes; 
} 
public void setAttributes(List<Attribute> attributes) { 
    this.attributes = attributes; 
} 

} 

Schritt 3: Erstellen Sie eine Klasse mit dem Namen DSML wie folgt:

DSML.java

import java.io.Serializable; 
import java.util.List; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlElementWrapper; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name = "dsml") 
public class DSML implements Serializable { 
private static final long serialVersionUID = 1L; 
private List<Student> entries; 

@XmlElementWrapper(name = "entries") 
@XmlElement(name = "entry", type = Student.class) 
public List<Student> getEntries() { 
    return entries; 
} 
public void setEntries(List<Student> entries) { 
    this.entries = entries; 
} 
} 

Schritt 4: Nun ist es Zeit XML in Java zu konvertieren Objekt wie folgt:

UsingRestAPI.java

JAXBContext jaxbContext = JAXBContext.newInstance(DSML.class); 
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
DSML dsml = (DSML) jaxbUnmarshaller.unmarshal(new StringReader(temp));