我试图解组一个大的xml文档的中间元素.目前正在使用JAXB和Woodstox.
我需要解组的xml中间元素的示例:
<Values>
<Person ID="ABC">
<FirstName>Shawn</FirstName>
<LastName>Mark</LastName>
<Age>3</Age>
</Person>
<Person ID="DEF">
<FirstName>John</FirstName>
<LastName>Durell</LastName>
<Age>4</Age>
</Person>
</Values>
Run Code Online (Sandbox Code Playgroud)
我使用的jaxb类是:
@XmlRootElement(name = "Values")
@XmlAccessorType(XmlAccessType.FIELD)
public class Attributes
{
@XmlElement(name = "Person")
private ArrayList<Person> persons;
public ArrayList<Person> getPersons()
{
return persons;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
public class Person
{
@XmlAttribute
private String ID;
@XmlElement(name = "FirstName")
private String firstName;
@XmlElement(name = "LastName")
private String lastName;
@XmlElement(name = "Age")
private String age;
}
Run Code Online (Sandbox Code Playgroud)
我可以解除除ID之外的所有值.它被显示为null.
这是代码:
final XMLInputFactory xif = XMLInputFactory.newInstance();
final StreamSource xml = new StreamSource(pathToxmlFile);
XMLStreamReader xsr;
xsr = xif.createXMLStreamReader(xml);
xsr.nextTag();
while (!xsr.getLocalName().equals("Values"))
{
xsr.nextTag();
}
final JAXBContext jc = JAXBContext.newInstance(Attributes.class);
final Unmarshaller unmarshaller = jc.createUnmarshaller();
final JAXBElement<Attributes> jb = unmarshaller.unmarshal(xsr, Attributes.class);
Run Code Online (Sandbox Code Playgroud)
上面的代码仅在<Values>从根目录嵌套5-6级时才起作用.如果之前存在15个标签<Values>,则此代码不起作用.
与仅使用JAXB和解组所有元素相比,它相对非常慢,但这需要我为永远不会使用的数据创建对象.
所以,我的问题是 - 无论如何都要提高性能?当它嵌套在xml深处时为什么不能工作?如何从Person属性中获取ID值?
以下应该有所帮助:
当它嵌套在xml深处时为什么不能工作?
如果不工作就意味着抛出一个例外:
Exception in thread "main" javax.xml.stream.XMLStreamException: ParseError at [row,col]:[4,13]
Message: found: CHARACTERS, expected START_ELEMENT or END_ELEMENT
at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.nextTag(XMLStreamReaderImpl.java:1247)
at blog.stax.middle.UnmarshalDemo.main(UnmarshalDemo.java:15)
Run Code Online (Sandbox Code Playgroud)
您可以更改前进XmlStreamReader到的代码:
while(xsr.hasNext()) {
if(xsr.isStartElement() && xsr.getLocalName().equals("Values")) {
break;
}
xsr.next();
}
Run Code Online (Sandbox Code Playgroud)
反正有提高性能吗?
StAX是一种解析XML文档的快速方法.它可能正在被您的JAXB实现使用.字符串比较可能很慢.由于您使用的是Woodstox并且它实际上是元素名称(请参阅:第6.1节字符串实习:http://woodstox.codehaus.org/FAQ ).您可以对字符串进行身份检查,而不是使用equals方法.
if(Boolean.TRUE.equals(xsr.getProperty("org.codehaus.stax2.internNames"))) {
while(xsr.hasNext()) {
if(xsr.isStartElement() && xsr.getLocalName() == "return") {
break;
}
xsr.next();
}
} else {
while(xsr.hasNext()) {
if(xsr.isStartElement() && xsr.getLocalName().equals("return")) {
break;
}
xsr.next();
}
}
Run Code Online (Sandbox Code Playgroud)
如何从Person属性中获取ID值?
默认情况下,您的JAXB(JSR-222)实现的XML将您的ID字段映射到一个被调用的属性,id而不是ID.您可以按如下方式覆盖此默认值:
@XmlAttribute(name="ID")
private String ID;
Run Code Online (Sandbox Code Playgroud)