倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

XMLEventFactory (4) : 要素 StartElement, EndElement

今回は要素に関する XML イベント。

  • StartElement
  • EndElement

StartElement


StartElement イベントは XMLEventFactory#createStartElement() メソッドによって生成します。 createStartElement() メソッドは次の4つが定義されています。

createStartElement(QName qname, Iterator atts, Iterator nss)
createStartElement(String prefix, String uri, String localName)
createStartElement(String prefix, String uri, String localName, Iterator atts, Iterator nss)
createStartElement(String prefix, String uri, String localName, Iterator atts, Iterator nss, NamespaceContext context)

ただし、

  • 「atts」は属性 (javax.xml.stream.events.Attribute) のイテレータ (Iterator)
  • 「nss」は名前空間宣言 (javax.xml.stream.events.Namespace) のイテレータ (Iterator)

です。 null の場合は、無視されます(空のイテレータと同じ)。

設定できるパラメータ

パラメータ デフォルト値
QName QName -
接頭辞 String ""
名前空間 URI String ""
ローカル名 String -
属性のイテレータ Iterator null
名前空間宣言のイテレータ Iterator null
名前空間コンテキスト NamespaceContext ?

EndElement


EndElement イベントは XMLEventFactory#createEndElement() メソッドによって生成します。 createEndElement() メソッドは次の1つのみが定義されています。

createEndElement(QName name, Iterator nss)
createEndElement(String prefix, String uri, String localName)
createEndElement(String prefix, String uri, String localName, Iterator nss)

「nss」は開始タグのときと同様に、名前空間宣言のイテレータ (Iterator) です。 null の場合、空のイテレータです。

設定できるパラメータ

パラメータ デフォルト値
QName QName -
接頭辞 String ""
名前空間 URI String ""
ローカル名 String -
名前空間宣言のイテレータ Iterator null

サンプル


各 createStartElement(), creeateEndElement() メソッドの挙動を見てみましょう。

  • Java コード:メソッド呼び出し(引数の指定)
  • toString():生成された XMLEvent オブジェクトに対して toString() メソッドを呼び出した際に返される文字列
  • XMLEventWriter:生成された XMLEvent オブジェクトに対して XMLEventWriter#add(XMLEvent) を呼び出した際に書き出される文字列

です。 また、要素の QName 「qname」、属性のイテレータ「atts」、名前空間宣言のイテレータ「nss」はそれぞれ以下のように生成したとします:

// <element/>
QName qname = new QName("uri", "element", "p");

XMLEventFactory factory = XMLEventFactory.newInstance();
// att="value"
Attribute att = factory.createAttribute(new QName("att"), "value");
Iterator<Attribute> atts = Collections.singletonList(att).iterator();

// xmlns:p="ns-uri"
Namespace ns = factory.createNamespace("ns-p", "ns-uri");
Iterator<Namespace> nss = Collections.singletonList(ns).iterator();

ではサンプルを。 同じような引数を持つ開始タグと終了タグの XML イベントをまとめて扱っています(普通そういう風に使うと思うので)。

Java コード createStartElement(qname, atts, nss)
createEndElement(qname, nss)
toString() <['uri']:p:element att='value' xmlns:ns-p='ns-uri'>
</['uri']:p:element>
XMLEventWriter <p:element xmlns:ns-p="ns-uri" att="value">
</p:element>
Java コード createStartElement("p", "uri", "element")
createEndElement("p", "uri", "element")
toString() <['uri']:p:element>
</['uri']:p:element>
XMLEventWriter <p:element>
</p:element>
Java コード createStartElement("p", "uri", "element", atts, nss)
createEndElement("p", "uri", "element", nss)
toString() <['uri']:p:element att='value' xmlns:ns-p='ns-uri'>
</['uri']:p:element>
XMLEventWriter <p:element xmlns:ns-p="ns-uri" att="value">
</p:element>

NamespaceContext を引数にとる createStartElement() メソッドは省略。

接頭辞の衝突

要素を生成する際に指定した(名前空間 URI、接頭辞)の組と、名前空間宣言を生成する際に指定した(名前空間 URI、接頭辞)の組は、接頭辞が同じで名前空間 URI が異なると、XML 文書としては矛盾が生じます(属性と名前空間宣言の場合も同じ)。 この状況を StartElement イベントを用いて作ってみると、以下のようになります:

// 接頭辞 "p" に名前空間 "ns-uri" をバインド
Namespace ns = factory.createNamespace("p", "ns-uri");
Iterator<Namespace> nss = Collections.singletonList(ns).iterator();

// 接頭辞 "p" に名前空間 "uri" をバインド
StartElement start = factory.createStartElement("p", "uri", "element", null, nss);
        
System.out.println(start);
// 「<['uri']:p:element xmlns:p='ns-uri'>」と出力される
        
writer.add(start);  // writer は XMLEventWriter のインスタンスとします
// 例外 XMLStreamException が投げられる

XMLEventWriter を用いて書き出す際には、キチンと例外が投げられます。 逆に言えば StartElement オブジェクトの時点では矛盾していても例外が投げられるようなことはないようです。