JavaにおけるXMLライブラリのサポート

JavaでのXMLライブラリのサポート

1. 前書き

この記事では、Java XMLライブラリーとAPIを比較します。

これは、XMLのJavaサポートに関するシリーズの2番目の記事です。JavaでのXPathサポートについて詳しく知りたい場合は、the previous articleを参照してください。

2. 概要

次に、XMLの世界のサポートをさらに掘り下げて、そのために、主題に関連するすべてのイニシャルをできるだけ簡単に説明することから始めます。

Java XMLサポートでは、APIの定義はほとんどなく、それぞれに長所と短所があります。

  • SAX:これはイベントベースの解析APIであり、低レベルのアクセスを提供し、メモリ効率が高く、ドキュメントツリー全体をメモリにロードしないため、DOMよりも高速ですが、次のようなナビゲーションのサポートは提供しません。 XPathによって提供されるものですが、より効率的ですが、使用するのも困難です。

  • DOM:ツリー構造ドキュメントをメモリにロードするモデルベースのパーサーとして、元の要素の順序があり、ドキュメントを双方向にナビゲートでき、読み取りと書き込み用のAPIを提供し、XML操作を提供します。価格はメモリリソースに大きな負担をかけますが、非常に使いやすいです。

  • StAX:DOMの使いやすさとSAXの効率を提供しますが、XML操作などのDOMによって提供される機能が不足しており、ドキュメントを前方にナビゲートすることしかできません。

  • JAXB:ドキュメントを両方向にナビゲートでき、DOMよりも効率的で、XMLからJavaタイプへの変換が可能で、XML操作をサポートしていますが、有効なXMLドキュメントのみを解析できます。

JAXPへの参照をいくつか見つけることができますが、このプロジェクトの最後のリリースは2013年3月からであり、実際には死んでいます。

XML Apis Table

XML APIテーブル

3. XML

このセクションでは、最も一般的な実装を確認し、実際の動作サンプルをテストして、それらの違いを確認します。

次の例では、次のような構造を持つ単純なXMLファイルを使用します。


    
        Guava
        Introduction to Guava
        04/04/2016
        GuavaAuthor
    
    ...

4. DOM4J

まず、DOM4Jで何ができるかを見ていきます。この例では、このdependencyの最後のバージョンを追加する必要があります。

これは、XMLファイルを操作するための最も人気のあるライブラリの1つです。これにより、双方向の読み取りを実行し、新しいドキュメントを作成し、既存のドキュメントを更新できます。

DOM4Jは、DOMSAXXPath、およびXLSTで機能します。 SAXJAXPを介してサポートされます。 __

たとえば、ここで、特定のIDでフィルタリングする要素を選択する方法を見てみましょう。

SAXReader reader = new SAXReader();
Document document = reader.read(file);
List elements = document.selectNodes("//*[@tutId='" + id + "']");
return elements.get(0);

SAXReaderクラスは、SAX解析イベントからDOM4Jツリーを作成する役割を果たします。 org.dom4j.Documentを取得したら、必要なメソッドを呼び出して、XPath式をString.として渡す必要があります。

既存のドキュメントをロードし、そのコンテンツを変更してから、元のファイルを更新できます。

for (Node node : nodes) {
    Element element = (Element)node;
    Iterator iterator = element.elementIterator("title");
    while (iterator.hasNext()) {
        Element title =(Element)iterator.next();
        title.setText(title.getText() + " updated");
    }
}
XMLWriter writer = new XMLWriter(
  new FileWriter(new File("src/test/resources/example_updated.xml")));
writer.write(document);
writer.close();

上記の例では、すべてのタイトルのコンテンツを変更し、新しいファイルを作成しています。

ここで、elementIteratorを呼び出し、node.の名前を渡すことで、リスト内のすべてのタイトルのnodeを取得するのがいかに簡単であるかに注目してください。

コンテンツを変更したら、DOM4Jツリーを取得してXMLとしてストリームにフォーマットするXMLWriterを使用します。

最初から新しいドキュメントを作成するのは、以下に示すように簡単です。

Document document = DocumentHelper.createDocument();
Element root = document.addElement("XMLTutorials");
Element tutorialElement = root.addElement("tutorial").addAttribute("tutId", "01");
tutorialElement.addAttribute("type", "xml");
tutorialElement.addElement("title").addText("XML with Dom4J");
...
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(
  new FileWriter(new File("src/test/resources/example_new.xml")), format);
writer.write(document);
writer.close();

DocumentHelperは、DOM4Jが使用するメソッドのコレクションを提供します。たとえば、createDocumentは、空のドキュメントを作成して作業を開始します。

DOM4Jが提供するメソッドを使用して、必要な数の属性または要素を作成できます。ドキュメントが完成したら、前の更新の場合と同じようにファイルに書き込むだけです。

5. JDOM

JDOM,を操作するには、このdependencyをpomに追加する必要があります。

JDOM’sの作業スタイルはDOM4J’sと非常に似ているため、いくつかの例を見ていきます。

SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(this.getFile());
Element tutorials = doc.getRootElement();
List titles = tutorials.getChildren("tutorial");

上記の例では、DOM4J:で実行できるように、非常に簡単な方法でルート要素からすべての要素を取得しています。

SAXBuilder builder = new SAXBuilder();
Document document = (Document) builder.build(file);
String filter = "//*[@tutId='" + id + "']";
XPathFactory xFactory = XPathFactory.instance();
XPathExpression expr = xFactory.compile(filter, Filters.element());
List node = expr.evaluate(document);

繰り返しになりますが、上記のコードでは、SAXBuilderが特定のファイルからDocumentインスタンスを作成しています。 JDOM2.によって提供されるXPathFactoryXPath式を渡すことにより、tutId属性によって要素を取得しています。

6. StAX

次に、Stax APIを使用してルート要素からすべての要素を取得する方法を見ていきます。 StaxはJava 6以降のJDKに含まれているため、依存関係を追加する必要はありません。

まず、Tutorialクラスを作成する必要があります。

public class Tutorial {
    private String tutId;
    private String type;
    private String title;
    private String description;
    private String date;
    private String author;

    // standard getters and setters
}

そして、私たちは従う準備ができています:

List tutorials = new ArrayList<>();
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader eventReader = factory.createXMLEventReader(new FileReader(this.getFile()));
Tutorial current;
while (eventReader.hasNext()) {
    XMLEvent event = eventReader.nextEvent();
    switch (event.getEventType()) {
        case XMLStreamConstants.START_ELEMENT:
            StartElement startElement = event.asStartElement();
            String qName = startElement.getName().getLocalPart();
            ...
            break;
        case XMLStreamConstants.CHARACTERS:
            Characters characters = event.asCharacters();
            ...
            break;
        case XMLStreamConstants.END_ELEMENT:
            EndElement endElement = event.asEndElement();

            // check if we found the closing element
            // close resources that need to be explicitly closed
            break;
    }
}

上記の例では、情報を取得するために、取得したデータを保存するクラスを作成する必要がありました。

ドキュメントを読むために、イベントハンドラーと呼ばれるものを宣言し、それらを使用してドキュメントを先にナビゲートしました。 SAXの実装は双方向ナビゲーションを提供しないことに注意してください。 ここでわかるように、要素の単純なリストを取得するためだけに多くの作業を行う必要があります。

7. JAXB

JAXBJDKとXercesに含まれているため、これに追加の依存関係は必要ありません。

JAXBを使用して、XMLファイルから情報をロード、作成、および操作するのは非常に簡単です。

XMLをバインドするための正しいJavaエンティティを作成する必要があります。それだけです。

JAXBContext jaxbContext = JAXBContext.newInstance(Tutorials.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Tutorials tutorials = (Tutorials) jaxbUnmarshaller.unmarshal(this.getFile());

上記の例では、XMLファイルをオブジェクトにロードし、そこからすべてを通常のJava構造として処理できます。

新しいドキュメントを作成するには、それを読むのと同じくらい簡単ですが、以下のコードのように逆の方法で行います。

まず、Tutorialクラスを変更して、JAXBアノテーションをgettersおよびsettersに追加します。

public class Tutorial {
    ...

    public String getTutId() {
        return tutId;
    }

    @XmlAttribute
    public void setTutId(String tutId) {
        this.tutId = tutId;
    }
    ...
    @XmlElement
    public void setTitle(String title) {
        this.title = title;
    }
    ...
}

@XmlRootElement
public class Tutorials {
    private List tutorial;

    // standard getters and setters with @XmlElement annotation
}

@XmlRootElementを使用して、ドキュメントのルートノードを表すオブジェクトを定義し、次に@XmlAttributeまたは@XmlElementを使用して、その属性がノードの属性を表すか、の要素を表すかを定義します。ドキュメント。

その後、次のことができます。

Tutorials tutorials = new Tutorials();
tutorials.setTutorial(new ArrayList<>());
Tutorial tut = new Tutorial();
tut.setTutId("01");
...
tutorials.getTutorial().add(tut);
JAXBContext jaxbContext = JAXBContext.newInstance(Tutorials.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(tutorials, file);

ご覧のとおり、この種類のファイルを操作するには、XMLファイルをJavaオブジェクトにバインドするのが最も簡単な方法です。

8. XPath式のサポート

複雑なXPath式を作成するには、Jaxenを使用できます。 これは、DOMXOMDOM4JJDOM.などのさまざまなオブジェクトモデルに適応できるオープンソースのXPathライブラリです。

XPath式を作成し、サポートされている多くのドキュメントに対してコンパイルできます。

String expression = "/tutorials/tutorial";
XPath path = new DOMXPath(expression);
List result = path.selectNodes(xmlDocument);

これを機能させるには、このdependencyをプロジェクトに追加する必要があります。

9. 結論

ご覧のとおり、XMLを操作するための多くのオプションがありますが、アプリケーションの要件に応じて、それらのいずれかを操作することも、効率と単純さのどちらかを選択する必要がある場合もあります。

この記事の完全な動作サンプルは、gitリポジトリhereにあります。