4 * License : The MIT License
5 * Copyright(c) 2010 MikuToga Partners
8 package jp.sfjp.mikutoga.xml;
10 import java.util.Iterator;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.NoSuchElementException;
14 import javax.xml.bind.DatatypeConverter;
15 import org.w3c.dom.Element;
16 import org.w3c.dom.Node;
21 public final class DomUtils {
24 private static final char BS_CHAR = (char) 0x005c;
32 throw new AssertionError();
36 * 要素からxsd:string型属性値を読み取る。
40 * @throws TogaXmlException 属性値が見つからなかった。
42 public static String getStringAttr(Element elem, String attrName)
43 throws TogaXmlException{
44 if( ! elem.hasAttribute(attrName) ){
45 String message = "Attr:[" + attrName + "] "
47 + "Elem:[" + elem.getTagName()+"]";
48 throw new TogaXmlException(message);
53 result = elem.getAttribute(attrName);
54 }catch(IllegalArgumentException e){
55 String message = "Invalid attribute form [" + attrName + "]";
56 throw new TogaXmlException(message, e);
63 * 要素からxsd:boolean型属性値を読み取る。
67 * @throws TogaXmlException 属性値が見つからなかった。
69 public static boolean getBooleanAttr(Element elem, String attrName)
70 throws TogaXmlException{
71 String value = getStringAttr(elem, attrName);
75 result = DatatypeConverter.parseBoolean(value);
76 }catch(IllegalArgumentException e){
78 "Invalid boolean attribute form "
79 + "[" + attrName + "][" + value + "]";
80 throw new TogaXmlException(message, e);
87 * 要素からxsd:integer型属性値を読み取る。
91 * @throws TogaXmlException 属性値が見つからなかった。
93 public static int getIntegerAttr(Element elem, String attrName)
94 throws TogaXmlException{
95 String value = getStringAttr(elem, attrName);
99 result = DatatypeConverter.parseInt(value);
100 }catch(IllegalArgumentException e){
102 "Invalid integer attribute form "
103 + "[" + attrName + "][" + value + "]";
104 throw new TogaXmlException(message, e);
111 * 要素からxsd:float型属性値を読み取る。
113 * @param attrName 属性名
115 * @throws TogaXmlException 属性値が見つからなかった。
117 public static float getFloatAttr(Element elem, String attrName)
118 throws TogaXmlException{
119 String value = getStringAttr(elem, attrName);
123 result = DatatypeConverter.parseFloat(value);
124 }catch(IllegalArgumentException e){
126 "Invalid float attribute form "
127 + "[" + attrName + "][" + value + "]";
128 throw new TogaXmlException(message, e);
135 * 要素から日本語Windows用ファイル名を属性値として読み取る。
136 * 念のため文字U+00A5は文字U-005Cに変換される。
138 * @param attrName 属性名
140 * @throws TogaXmlException 属性値が見つからなかった。
142 public static String getSjisFileNameAttr(Element elem, String attrName)
143 throws TogaXmlException{
146 result = getStringAttr(elem, attrName);
147 }catch(IllegalArgumentException e){
149 "Invalid winfile attribute form "
150 + "[" + attrName + "]";
151 throw new TogaXmlException(message, e);
154 result = result.replace("" + '\u00a5', "" + BS_CHAR);
160 * 指定された名前の子要素を1つだけ返す。
162 * @param tagName 子要素名
164 * @throws TogaXmlException 1つも見つからなかった
166 public static Element getChild(Element parent, String tagName)
167 throws TogaXmlException{
168 Element result = null;
170 for(Node node = parent.getFirstChild();
172 node = node.getNextSibling() ){
174 if(node.getNodeType() != Node.ELEMENT_NODE) continue;
175 Element elem = (Element) node;
177 String elemTagName = elem.getTagName();
178 if( tagName.equals(elemTagName) ){
186 "Elem:[" + tagName + "] was not found in "
187 +"Elem:[" + parent.getTagName() + "]";
188 throw new TogaXmlException(message);
195 * 親要素が指定された名前の子要素を持つか判定する。
197 * @param tagName 子要素名
198 * @return 指定名の子要素が存在すればtrue
200 public static boolean hasChild(Element parent, String tagName){
201 for(Node node = parent.getFirstChild();
203 node = node.getNextSibling() ){
205 if(node.getNodeType() != Node.ELEMENT_NODE) continue;
206 Element elem = (Element) node;
208 String elemTagName = elem.getTagName();
209 if( tagName.equals(elemTagName) ) return true;
216 * 指定された名前の子要素のリストを返す。
218 * @param childTag 子要素名
221 public static List<Element> getChildList(Element parent,
223 List<Element> result = new LinkedList<Element>();
225 for(Node node = parent.getFirstChild();
227 node = node.getNextSibling() ){
229 if(node.getNodeType() != Node.ELEMENT_NODE) continue;
230 Element elem = (Element) node;
232 String tagName = elem.getTagName();
233 if( ! childTag.equals(tagName) ) continue;
242 * 指定された名前の子要素の列挙子を返す。
244 * @param childTag 子要素名
247 public static Iterator<Element> getChildIterator(Element parent,
251 firstElem = getChild(parent, childTag);
252 }catch(TogaXmlException e){
256 Iterator<Element> result = new ElemIterator(firstElem);
262 * 指定された名前の子要素のforeachを返す。
264 * @param childTag 子要素名
265 * @return 子要素のforeach
267 public static Iterable<Element> getEachChild(Element parent,
269 final Iterator<Element> iterator = getChildIterator(parent, childTag);
270 Iterable<Element> result = new Iterable<Element>(){
272 public Iterator<Element> iterator(){
282 * @return 次の要素。なければnull
284 public static Element nextElement(Element elem){
285 Node nextNode = elem;
287 nextNode = nextNode.getNextSibling();
288 if(nextNode == null) break;
289 if(nextNode.getNodeType() == Node.ELEMENT_NODE){
294 return (Element) nextNode;
300 * @return 次の要素。なければnull
302 public static Element nextNamedElement(Element elem){
303 String tagName = elem.getTagName();
304 Element nextElem = elem;
306 nextElem = nextElement(nextElem);
307 if(nextElem == null) break;
308 if(tagName.equals(nextElem.getTagName())) break;
315 * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。
317 private static final class ElemIterator implements Iterator<Element> {
318 private Element next;
322 * @param elem 最初の要素。nullを指定すれば空列挙子となる。
324 ElemIterator(Element elem){
331 * @return {@inheritDoc}
334 public boolean hasNext(){
335 if(this.next == null) return false;
341 * @return {@inheritDoc}
342 * @throws NoSuchElementException {@inheritDoc}
345 public Element next() throws NoSuchElementException{
346 if(this.next == null) throw new NoSuchElementException();
347 Element result = this.next;
348 this.next = nextNamedElement(this.next);
357 public void remove(){
358 throw new UnsupportedOperationException();