OSDN Git Service

6cd09ba737a86045880bf27417ad63e1895109b2
[mikutoga/TogaGem.git] / src / main / java / jp / sourceforge / mikutoga / xml / DomUtils.java
1 /*\r
2  * XML DOM utilities\r
3  *\r
4  * License : The MIT License\r
5  * Copyright(c) 2010 MikuToga Partners\r
6  */\r
7 \r
8 package jp.sourceforge.mikutoga.xml;\r
9 \r
10 import java.util.Iterator;\r
11 import java.util.LinkedList;\r
12 import java.util.List;\r
13 import java.util.NoSuchElementException;\r
14 import javax.xml.bind.DatatypeConverter;\r
15 import org.w3c.dom.Element;\r
16 import org.w3c.dom.Node;\r
17 \r
18 /**\r
19  * DOMユーティリティ。\r
20  */\r
21 public final class DomUtils {\r
22 \r
23     /**\r
24      * 隠しコンストラクタ。\r
25      */\r
26     private DomUtils(){\r
27         super();\r
28         assert false;\r
29         throw new AssertionError();\r
30     }\r
31 \r
32     /**\r
33      * 要素からxsd:string型属性値を読み取る。\r
34      * @param elem 要素\r
35      * @param attrName 属性名\r
36      * @return 文字列\r
37      * @throw TogaXmlException 属性値が見つからなかった。\r
38      */\r
39     public static String getStringAttr(Element elem, String attrName)\r
40             throws TogaXmlException{\r
41         if( ! elem.hasAttribute(attrName) ){\r
42             String message = "Attr:[" + attrName + "] "\r
43                     + "was not found in "\r
44                     + "Elem:[" + elem.getTagName()+"]";\r
45             throw new TogaXmlException(message);\r
46         }\r
47 \r
48         String result;\r
49         try{\r
50             result = elem.getAttribute(attrName);\r
51         }catch(IllegalArgumentException e){\r
52             String message = "Invalid attribute form [" + attrName + "]";\r
53             throw new TogaXmlException(message, e);\r
54         }\r
55 \r
56         return result;\r
57     }\r
58 \r
59     /**\r
60      * 要素からxsd:boolean型属性値を読み取る。\r
61      * @param elem 要素\r
62      * @param attrName 属性名\r
63      * @return 真ならtrue\r
64      * @throw TogaXmlException 属性値が見つからなかった。\r
65      */\r
66     public static boolean getBooleanAttr(Element elem, String attrName)\r
67             throws TogaXmlException{\r
68         String value = getStringAttr(elem, attrName);\r
69 \r
70         boolean result;\r
71         try{\r
72             result = DatatypeConverter.parseBoolean(value);\r
73         }catch(IllegalArgumentException e){\r
74             String message =\r
75                     "Invalid boolean attribute form "\r
76                     + "[" + attrName + "][" + value + "]";\r
77             throw new TogaXmlException(message, e);\r
78         }\r
79 \r
80         return result;\r
81     }\r
82 \r
83     /**\r
84      * 要素からxsd:integer型属性値を読み取る。\r
85      * @param elem 要素\r
86      * @param attrName 属性名\r
87      * @return int値\r
88      * @throw TogaXmlException 属性値が見つからなかった。\r
89      */\r
90     public static int getIntegerAttr(Element elem, String attrName)\r
91             throws TogaXmlException{\r
92         String value = getStringAttr(elem, attrName);\r
93 \r
94         int result;\r
95         try{\r
96             result = DatatypeConverter.parseInt(value);\r
97         }catch(IllegalArgumentException e){\r
98             String message =\r
99                     "Invalid integer attribute form "\r
100                     + "[" + attrName + "][" + value + "]";\r
101             throw new TogaXmlException(message, e);\r
102         }\r
103 \r
104         return result;\r
105     }\r
106 \r
107     /**\r
108      * 要素からxsd:float型属性値を読み取る。\r
109      * @param elem 要素\r
110      * @param attrName 属性名\r
111      * @return float値\r
112      * @throw TogaXmlException 属性値が見つからなかった。\r
113      */\r
114     public static float getFloatAttr(Element elem, String attrName)\r
115             throws TogaXmlException{\r
116         String value = getStringAttr(elem, attrName);\r
117 \r
118         float result;\r
119         try{\r
120             result = DatatypeConverter.parseFloat(value);\r
121         }catch(IllegalArgumentException e){\r
122             String message =\r
123                     "Invalid float attribute form "\r
124                     + "[" + attrName + "][" + value + "]";\r
125             throw new TogaXmlException(message, e);\r
126         }\r
127 \r
128         return result;\r
129     }\r
130 \r
131     /**\r
132      * 要素から日本語Windows用ファイル名を属性値として読み取る。\r
133      * 念のため文字U+00A5は文字U-005Cに変換される。\r
134      * @param elem 要素\r
135      * @param attrName 属性名\r
136      * @return ファイル名\r
137      * @throw TogaXmlException 属性値が見つからなかった。\r
138      */\r
139     public static String getSjisFileNameAttr(Element elem, String attrName)\r
140             throws TogaXmlException{\r
141         String result;\r
142         try{\r
143             result = getStringAttr(elem, attrName);\r
144         }catch(IllegalArgumentException e){\r
145             String message =\r
146                     "Invalid winfile attribute form "\r
147                     + "[" + attrName + "]";\r
148             throw new TogaXmlException(message, e);\r
149         }\r
150 \r
151         result.replace("" + '\u00a5', "" + '\u005c\u005c');\r
152 \r
153         return result;\r
154     }\r
155 \r
156     /**\r
157      * 指定された名前の子要素を1つだけ返す。\r
158      * @param parent 親要素\r
159      * @param tagName 子要素名\r
160      * @return 子要素\r
161      * @throw TogaXmlException 1つも見つからなかった\r
162      */\r
163     public static Element getChild(Element parent, String tagName)\r
164             throws TogaXmlException{\r
165         Element result = null;\r
166 \r
167         for(Node node = parent.getFirstChild();\r
168             node != null;\r
169             node = node.getNextSibling() ){\r
170 \r
171             if(node.getNodeType() != Node.ELEMENT_NODE) continue;\r
172             Element elem = (Element) node;\r
173 \r
174             String elemTagName = elem.getTagName();\r
175             if( tagName.equals(elemTagName) ){\r
176                 result = elem;\r
177                 break;\r
178             }\r
179         }\r
180 \r
181         if(result == null){\r
182             String message =\r
183                     "Elem:[" + tagName + "] was not found in "\r
184                     +"Elem:[" + parent.getTagName() + "]";\r
185             throw new TogaXmlException(message);\r
186         }\r
187 \r
188         return result;\r
189     }\r
190 \r
191     /**\r
192      * 親要素が指定された名前の子要素を持つか判定する。\r
193      * @param parent 親要素\r
194      * @param tagName 子要素名\r
195      * @return 指定名の子要素が存在すればtrue\r
196      */\r
197     public static boolean hasChild(Element parent, String tagName){\r
198         for(Node node = parent.getFirstChild();\r
199             node != null;\r
200             node = node.getNextSibling() ){\r
201 \r
202             if(node.getNodeType() != Node.ELEMENT_NODE) continue;\r
203             Element elem = (Element) node;\r
204 \r
205             String elemTagName = elem.getTagName();\r
206             if( tagName.equals(elemTagName) ) return true;\r
207         }\r
208 \r
209         return false;\r
210     }\r
211 \r
212     /**\r
213      * 指定された名前の子要素のリストを返す。\r
214      * @param parent 親要素\r
215      * @param childTag 子要素名\r
216      * @return 子要素のリスト\r
217      */\r
218     public static List<Element> getChildList(Element parent,\r
219                                                String childTag){\r
220         List<Element> result = new LinkedList<Element>();\r
221 \r
222         for(Node node = parent.getFirstChild();\r
223             node != null;\r
224             node = node.getNextSibling() ){\r
225 \r
226             if(node.getNodeType() != Node.ELEMENT_NODE) continue;\r
227             Element elem = (Element) node;\r
228 \r
229             String tagName = elem.getTagName();\r
230             if( ! childTag.equals(tagName) ) continue;\r
231 \r
232             result.add(elem);\r
233         }\r
234 \r
235         return result;\r
236     }\r
237 \r
238     /**\r
239      * 指定された名前の子要素の列挙子を返す。\r
240      * @param parent 親要素\r
241      * @param childTag 子要素名\r
242      * @return 子要素の列挙子\r
243      */\r
244     public static Iterator<Element> getChildIterator(Element parent,\r
245                                                        String childTag){\r
246         Element firstElem;\r
247         try{\r
248             firstElem = getChild(parent, childTag);\r
249         }catch(TogaXmlException e){\r
250             firstElem = null;\r
251         }\r
252 \r
253         Iterator<Element> result = new ElemIterator(firstElem);\r
254 \r
255         return result;\r
256     }\r
257 \r
258     /**\r
259      * 指定された名前の子要素のforeachを返す。\r
260      * @param parent 親要素\r
261      * @param childTag 子要素名\r
262      * @return 子要素のforeach\r
263      */\r
264     public static Iterable<Element> getEachChild(Element parent,\r
265                                                    String childTag){\r
266         final Iterator<Element> iterator = getChildIterator(parent, childTag);\r
267         Iterable<Element> result = new Iterable<Element>(){\r
268             public Iterator<Element> iterator(){\r
269                 return iterator;\r
270             }\r
271         };\r
272         return result;\r
273     }\r
274 \r
275     /**\r
276      * 要素の次の要素を返す。\r
277      * @param elem 要素\r
278      * @return 次の要素。なければnull\r
279      */\r
280     public static Element nextElement(Element elem){\r
281         Node nextNode = elem;\r
282         for(;;){\r
283             nextNode = nextNode.getNextSibling();\r
284             if(nextNode == null) break;\r
285             if(nextNode.getNodeType() == Node.ELEMENT_NODE){\r
286                 break;\r
287             }\r
288         }\r
289 \r
290         return (Element) nextNode;\r
291     }\r
292 \r
293     /**\r
294      * 同じ要素名を持つ次の要素を返す。\r
295      * @param elem 要素\r
296      * @return 次の要素。なければnull\r
297      */\r
298     public static Element nextNamedElement(Element elem){\r
299         String tagName = elem.getTagName();\r
300         Element nextElem = elem;\r
301         for(;;){\r
302             nextElem = nextElement(nextElem);\r
303             if(nextElem == null) break;\r
304             if(tagName.equals(nextElem.getTagName())) break;\r
305         }\r
306 \r
307         return nextElem;\r
308     }\r
309 \r
310     /**\r
311      * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。\r
312      */\r
313     private static class ElemIterator implements Iterator<Element>{\r
314         private Element next;\r
315 \r
316         /**\r
317          * コンストラクタ。\r
318          * @param elem 最初の要素。nullを指定すれば空列挙子となる。\r
319          */\r
320         private ElemIterator(Element elem){\r
321             super();\r
322             this.next = elem;\r
323         }\r
324 \r
325         /**\r
326          * {@inheritDoc}\r
327          * @return {@inheritDoc}\r
328          */\r
329         public boolean hasNext(){\r
330             if(this.next == null) return false;\r
331             return true;\r
332         }\r
333 \r
334         /**\r
335          * {@inheritDoc}\r
336          * @return {@inheritDoc}\r
337          * @throws NoSuchElementException {@inheritDoc}\r
338          */\r
339         public Element next() throws NoSuchElementException{\r
340             if(this.next == null) throw new NoSuchElementException();\r
341             Element result = this.next;\r
342             this.next = nextNamedElement(this.next);\r
343             return result;\r
344         }\r
345 \r
346         /**\r
347          * {@inheritDoc}\r
348          * ※ 未サポート。\r
349          */\r
350         public void remove(){\r
351             throw new UnsupportedOperationException();\r
352         }\r
353 \r
354     }\r
355 \r
356 }\r