今回は XMLStreamReader#getElementText() メソッドを見ていきます。
getElementText() メソッドは、要素の開始と要素の終了で挟まれたテキストを返します。 これは XML で書かれたプロパティファイルを処理する際に便利です。
例えば
<book> <title>なぜ宇宙人は地球に来ない?</title> <author>松尾貴史</author> <publisher>PHP新書</publisher> </book>
という XML 文書があるとします。 「現在の XML イベント」が <title> 要素の開始の位置にある場合、getElementText() を呼び出すと文字列「なぜ宇宙人は地球に来ない?」が返されます。 呼び出し後の「現在の XML イベント」は <title> 要素の終了となります。
解析の際の処理は、現れた XML イベントの種類によって次の4種類に分類できます。 各 XML イベントに対する処理は以下のようになっています:
XML イベント | 処理 |
---|---|
CHARACTERS CDATA SPACE ENTITY_REFERENCE |
返すべき文字列に現在の文字列(getText() の返り値)を付加して次の XML イベントを処理する。 |
COMMENT PROCESSING_INSTRUCTION |
次の XML イベントを処理する。 |
END_ELEMENT | 文字列を返して、getElementText() の解析を終了する |
START_DOCUMENT END_DOCUMENT START_ELEMENT ATTRIBUTE NAMESPACE DTD ENTITY_DECLARATION NOTATION_DECLARATION |
XMLStreamException を投げる。 |
幾つか注意を:
- getElementText() が呼ばれる直前には、現在のイベントは「要素の開始」でなければなりません(事前条件)
- getElementText() が呼ばれた直後では、現在のイベントは「要素の終了」でなければなりません(事後条件)
実装例
XMLStreamReader#getElementText() の JavaDoc に載っている実装例(StringBuffer を StringBuilder に変えています):
public String getElementText() throws XMLStreamException { if(getEventType() != START_ELEMENT) { throw new XMLStreamException( "parser must be on START_ELEMENT to read next text", getLocation()); } int eventType = next(); StringBuilder content = new StringBuilder(); while(eventType != END_ELEMENT) { if(eventType == CHARACTERS || eventType == CDATA || eventType == SPACE || eventType == ENTITY_REFERENCE) { content.append(getText()); } else if(eventType == PROCESSING_INSTRUCTION || eventType == COMMENT) { // skipping } else if(eventType == END_DOCUMENT) { throw new XMLStreamException( "unexpected end of document when reading element text content", getLocation()); } else if(eventType == START_ELEMENT) { throw new XMLStreamException( "element text content may not contain START_ELEMENT", getLocation()); } else { throw new XMLStreamException( "Unexpected event type "+eventType, getLocation()); } eventType = next(); } return content.toString(); }
switch 文を使った実装例:
public boolean isStartElement(){...} public int next(){...} public String getText(){...} public Location getLocation(){...} public String getElementText() throws XMLStreamException { if(!isStartElement()) throw new XMLStreamException( "現在のイベントは START_ELEMENT でなければなりません。", getLocation()); StringBuilder content = new StringBuilder(); while(true){ int type = next(); switch(type){ case CHARACTERS: case CDATA: case SPACE: case ENTITY_REFERENCE: content.append(getText()); continue; case PROCESSING_INSTRUCTION: case COMMENT: continue; case END_ELEMENT: return content.toString(); case START_DOCUMENT: case END_DOCUMENT: case START_ELEMENT: case ATTRIBUTE: case NAMESPACE: case DTD: case ENTITY_DECLARATION: case NOTATION_DECLARATION: default: throw new XMLStreamException( "許されないイベントが現れました。", getLocation()); } } }