我是Rest API的新手。我有一个xml输出,我需要解组。下面是xml输出:
<dsml>
<entries>
<entry dn="uid=7686,c=in,ou=pages,o=example.com">
<att name="uid">
<value>7568766</value>
</att>
<att name="email">
<value>new@gmail.com</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>old@gmail.com</value>
</att>
<att name="callname">
<value>rahul</value>
</att>
</entry>
</entries>
</dsml>
实际的xml输出共有37个条目。以下是模型类:
@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;
}
}
以下是Rest Api类代码:
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();
}
}
}
执行此代码时,我收到错误
javax.xml.bind.UnmarshalException - 链接异常: [org.xml.sax.SAXParseException; lineNumber:1; columnNumber:110;外部DTD:无法读取外部DTD“dsml.dtd”,因为由于accessExternalDTD属性设置的限制而不允许“http”访问。]
我已尝试将属性ACCESS_EXTERNAL_DTD更改为true,但它又出现了另一个错误:
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)
答案 0 :(得分:0)
(编辑回答:编辑了UserClass和DsmlFactory getEntities()方法)
我认为这是因为你的Xml结构和你的类结构不同。我永远不会使用具有相同名称但不同值类型的元素(例如您的att
和value
元素)。为什么?对于Marshaller来说这不是问题,对于Unmarshaller来说这是一个问题。因为,据我所知,它无法根据父项name
属性定义子元素值的类型。即使您定义了泛型类型的静态内部类(例如interface Attribute<V>
和static class Uid<Integer>
,static class Email<String>
等等,您的工作也会更复杂。
但是如果你写了@XmlElement(name="att") Set<Attribute> attributes
,其中属性计数对于Marshaller和Unmarshaller来说并不重要,那么它就是其他东西。
但是为了简单起见,我真的会推荐结构<email>{value}</email>
,<uid>{value}</uid>
等。
我已经制作了一个简单的Xml Marshaller / Unmarshaller进行测试(没有REST),这有效:
我的Dslm
Xml根类:
@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();
}
}
我的Entities
课程:
@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");
}
}
}
我的User
课程:
@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);
}
}
我的DsmlFactory
Marshaller / Unmarshaller测试类(确保您拥有D:\
分区,并且您拥有Read | ReadWrite权限,或者在方法saveXml()
和{{}中键入任何其他路径1}}:
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();
}
}
TestDrive:
main
答案 1 :(得分:0)
为什么不将Xml保存在文件中,然后将其传递给unmarshal
新版本_:
User user = (User) jaxbUnmarshaller.unmarshal(new File("c:/temp/user.xml") );//File path
它不会给出任何错误。
访问 - :http://howtodoinjava.com/jaxb/jaxb-exmaple-marshalling-and-unmarshalling-list-or-set-of-objects/
答案 2 :(得分:0)
我建议您尝试以下方法:
步骤1:创建名为Attribute
的类,如下所示:
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;
}
}
第2步:请修改名为Student
的班级,如下所示:
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;
}
}
步骤3:请创建一个名为DSML
的类,如下所示:
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;
}
}
步骤4:现在是时候将XML转换为Java对象,如下所示:
UsingRestAPI.java
JAXBContext jaxbContext = JAXBContext.newInstance(DSML.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
DSML dsml = (DSML) jaxbUnmarshaller.unmarshal(new StringReader(temp));