3

我正在尝试解组大型 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>

我使用的 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;
}

我能够解组除 ID 之外的所有值。它显示为空。

这是代码:

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);

上面的代码仅在<Values>从根嵌套 5-6 层时才有效。如果之前存在 15 个标签<Values>,则此代码不起作用。

与仅使用 JAXB 和解组所有元素相比,它也相对非常慢,但这需要我为永远不会使用的数据创建对象。

所以,我的问题是——有没有办法提高性能?为什么它嵌套在 xml 深处时不起作用?如何从 Person 属性中获取 ID 值?

4

1 回答 1

7

以下内容应该有所帮助:


为什么它嵌套在 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)

您可以将推进的代码更改XmlStreamReader为:

    while(xsr.hasNext()) {
        if(xsr.isStartElement() && xsr.getLocalName().equals("Values")) {
            break;
        }
        xsr.next();
    }

有没有办法提高性能?

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();
        }
    }

如何从 Person 属性中获取 ID 值?

默认情况下,您的 JAXB (JSR-222) 实现的 XML 会将您的ID字段映射到名为id而不是的属性ID。您可以按如下方式覆盖此默认值:

@XmlAttribute(name="ID")
private String ID;
于 2012-08-29T08:36:52.947 回答