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

1前書き

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

これは、XMLのJavaサポートに関するシリーズの2回目の記事です。JavaでのXPathサポートについて詳しく知りたい場合は、 前の記事

2概要

今、私たちはXMLの世界的なサポートをより深く掘り下げるつもりです、そしてそのために我々はすべての主題に関連したイニシャルをできるだけ簡単に説明することから始めます。

Java XMLサポートでは、API定義をいくつか見つけることができますが、それぞれに長所と短所があります。

SAX :イベントベースの解析APIであり、低レベルのアクセスを提供し、ドキュメントツリー全体をメモリにロードしないため、DOMよりメモリ効率がよく、高速です。 XPathで提供されているものもありますが、より効率的ですが、使用するのが難しいです。

DOM :ツリー構造の文書をメモリにロードするモデルベースのパーサーとして、元の要素の順序を持​​ち、文書を双方向にナビゲートでき、読み書き用のAPIを提供し、XML操作を提供します価格はメモリリソースへの高い負担ですが非常に使いやすいです。

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

JAXB :文書を双方向にナビゲートすることを可能にします。DOMよりも効率的で、XMLからJava型への変換が可能で、XML操作をサポートしますが、有効なXML文書しか解析できません。

リンク:/uploads/xmlapi__table-1.png[]

XML APIテーブル

** 3 XML

**

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

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

<tutorials>
    <tutorial tutId="01" type="java">
        <title>Guava</title>
        <description>Introduction to Guava</description>
        <date>04/04/2016</date>
        <author>GuavaAuthor</author>
    </tutorial>
    ...
</tutorials>

4 DOM4J

DOM4J を使って何ができるかを見てみることから始めます。この例では、このhttp://mvnrepository.com/artifact/dom4j/dom4j[依存関係]の最後のバージョンを追加する必要があります。

これは、 XML ファイルを扱うための最も人気のあるライブラリの1つです。双方向の読み取りを実行し、新しい文書を作成し、既存のものを更新することを可能にするからです。

DOM4J は、 DOM SAX XPathおよび XLSTと連携できます。 SAX JAXP . + でサポートされています

たとえば、ここで見てみましょう。与えられたIDでフィルタリングする要素をどのように選択できるのでしょうか。

SAXReader reader = new SAXReader();
Document document = reader.read(file);
List<Node> 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<Element> 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を使用するには、このhttps://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.jdom%22[dependency]をpomに追加する必要があります。

JDOMの 作業スタイルは DOM4Jの と非常によく似ています。

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

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

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

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

6. StAX

それでは、 Stax API を使用して、ルート要素からすべての要素を取得する方法を説明します。 Java 6以降、 Stax 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<Tutorial> 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

JAXB は、Xercesと同様に JDK に含まれています。

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> 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を使用できます。これは、 DOM XOM DOM4J 、および JDOM. など、さまざまなオブジェクトモデルに対応できるオープンソースのXPathライブラリです。

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

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

うまく機能させるには、このhttp://mvnrepository.com/artifact/jaxen/jaxen/1.1.6[依存関係]をプロジェクトに追加する必要があります。

9結論

アプリケーションの要件に応じて XML を扱うための多くのオプションがあることがわかるように、それらのうちのどれでも扱うことができるか、効率と単純さの間で選択しなければならないかもしれません。

この記事の完全なサンプルは、私たちのgitリポジトリhttps://github.com/eugenp/tutorials/tree/master/xml[here]にあります。