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 以外のすべての値を非整列化できます。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);

上記のコードは<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 メソッドの代わりに、文字列に対して ID チェックを行うことができます。

     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という属性にマップします。このデフォルトを次のようにオーバーライドできます。idID

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