OSDN Git Service

91be3029c373966963e1979021a3e568ea9de338
[mikutoga/TogaGem.git] / src / main / java / jp / sourceforge / mikutoga / xml / DomNsUtils.java
1 /*
2  * XML DOM utilities with namespace
3  *
4  * License : The MIT License
5  * Copyright(c) 2011 MikuToga Partners
6  */
7
8 package jp.sourceforge.mikutoga.xml;
9
10 import java.text.MessageFormat;
11 import java.util.Iterator;
12 import javax.xml.bind.DatatypeConverter;
13 import org.w3c.dom.DOMException;
14 import org.w3c.dom.Element;
15 import org.w3c.dom.Node;
16
17 /**
18  * DOMユーティリティ(名前空間対応)。
19  * <p>各種名前空間引数にnullが渡された場合、全ての名前空間にマッチする。
20  * <p>各種ローカル名引数にnullが渡された場合、全てのローカル名にマッチする。
21  * <p>ノードの持つ名前空間がnullの場合、全ての名前空間引数にマッチする。
22  */
23 public final class DomNsUtils {
24
25     private static final String ERRMSG_NOELEM =
26             "Elem:[{0}] was not found in Elem:[{1}]";
27     private static final String ERRMSG_NOATTR =
28             "Attr:[{0}] was not found in Elem:[{1}]";
29     private static final String ERRMSG_INVATTR =
30             "Invalid attribute form Attr[{0}] Value[{1}]";
31
32
33     /**
34      * 隠しコンストラクタ。
35      */
36     private DomNsUtils(){
37         assert false;
38         throw new AssertionError();
39     }
40
41
42     /**
43      * 名前空間とローカル名が一致するノードか判定する。
44      * @param node ノード
45      * @param nsuri 名前空間URI
46      * @param localName ローカル名。
47      * @return ノードの名前空間およびローカル名が一致したらtrue
48      */
49     public static boolean hasNsLocalNameNode(Node node,
50                                                 String nsuri,
51                                                 String localName ){
52         String nodeLocalName = node.getLocalName();
53         String nodeNsUri     = node.getNamespaceURI();
54
55         if(localName != null){
56             if( ! localName.equals(nodeLocalName) ) return false;
57         }
58
59         if(nsuri != null && nodeNsUri != null){
60             if( ! nsuri.equals(nodeNsUri) ) return false;
61         }
62
63         return true;
64     }
65
66     /**
67      * 名前空間とローカル名が一致する要素か判定する。
68      * @param node ノード
69      * @param nsuri 名前空間URI
70      * @param localName ローカル名。
71      * @return 名前空間およびローカル名が一致する要素であればtrue
72      */
73     public static boolean hasNsLocalNameElem(Node node,
74                                              String nsuri,
75                                              String localName ){
76         if(node.getNodeType() != Node.ELEMENT_NODE) return false;
77         if( ! hasNsLocalNameNode(node, nsuri, localName) ) return false;
78         return true;
79     }
80
81     /**
82      * 親要素が指定された名前の子要素を持つか判定する。
83      * @param parent 親要素
84      * @param nsuri 名前空間URI
85      * @param localName ローカル名
86      * @return 指定名の子要素が存在すればtrue
87      */
88     public static boolean hasChild(Element parent,
89                                     String nsuri,
90                                     String localName ){
91         for(Node node = parent.getFirstChild();
92             node != null;
93             node = node.getNextSibling() ){
94
95             if(hasNsLocalNameElem(node, nsuri, localName)){
96                 return true;
97             }
98         }
99
100         return false;
101     }
102
103     /**
104      * 指定された名前空間とローカル名に合致する最初の直下子要素を返す。
105      * @param parent 親要素
106      * @param nsuri 名前空間URI
107      * @param localName ローカル名
108      * @return 最初の直下子要素。見つからなければnull。
109      */
110     public static Element pickFirstChild(Node parent,
111                                          String nsuri,
112                                          String localName ){
113         Node node = parent.getFirstChild();
114         while(node != null){
115             if(hasNsLocalNameElem(node, nsuri, localName)){
116                 break;
117             }
118             node = node.getNextSibling();
119         }
120         return (Element) node;
121     }
122
123     /**
124      * 指定された名前空間とローカル名に合致する最初の直下子要素を返す。
125      * <p>見つからなければ例外を投げる。
126      * @param parent 親要素
127      * @param nsuri 名前空間URI
128      * @param localName ローカル名
129      * @return 最初の直下子要素。
130      * @throws TogaXmlException 1つも見つからなかった
131      */
132     public static Element getFirstChild(Element parent,
133                                         String nsuri,
134                                         String localName )
135             throws TogaXmlException{
136         Element elem = pickFirstChild(parent, nsuri, localName);
137
138         if(elem == null){
139             String message = MessageFormat.format(ERRMSG_NOELEM,
140                                                   localName,
141                                                   parent.getLocalName() );
142             throw new TogaXmlException(message);
143         }
144
145         return elem;
146     }
147
148     /**
149      * 指定された名前の子要素のforeachを返す。
150      * @param parent 親要素
151      * @param nsuri 名前空間URI
152      * @param localName 子要素名
153      * @return 子要素のforeach
154      */
155     public static Iterable<Element> getEachChild(final Element parent,
156                                                  final String nsuri,
157                                                  final String localName ){
158         Iterable<Element> result = new Iterable<Element>(){
159             @Override
160             public Iterator<Element> iterator(){
161                 return new SiblingElemIterator(parent, nsuri, localName);
162             }
163         };
164         return result;
165     }
166
167     /**
168      * 要素に属性が存在するか判定する。
169      * @param elem 要素
170      * @param nsuri 名前空間URI
171      * @param localName ローカル名
172      * @return 存在するならtrue
173      */
174     public static boolean hasAttrNS(Element elem,
175                                     String nsuri,
176                                     String localName ){
177         return elem.hasAttributeNS(nsuri, localName);
178     }
179
180     /**
181      * 要素からxsd:string型属性値を読み取る。
182      * @param elem 要素
183      * @param nsuri 名前空間URI
184      * @param localName 属性名
185      * @return 文字列
186      * @throws TogaXmlException 属性値が見つからなかった。
187      */
188     public static String getStringAttrNS(Element elem,
189                                          String nsuri,
190                                          String localName )
191             throws TogaXmlException{
192         if( ! hasAttrNS(elem, nsuri, localName) ){
193             String message = MessageFormat.format(ERRMSG_NOATTR,
194                                                   localName,
195                                                   elem.getLocalName() );
196             throw new TogaXmlException(message);
197         }
198
199         String result;
200         try{
201             result = elem.getAttributeNS(nsuri, localName);
202         }catch(DOMException e){
203             assert false;
204             throw new AssertionError(e);
205         }
206
207         return result;
208     }
209
210     /**
211      * 要素からxsd:boolean型属性値を読み取る。
212      * @param elem 要素
213      * @param nsuri 名前空間URI
214      * @param localName 属性名
215      * @return 真ならtrue
216      * @throws TogaXmlException 属性値が見つからなかった。
217      */
218     public static boolean getBooleanAttrNS(Element elem,
219                                            String nsuri,
220                                            String localName )
221             throws TogaXmlException{
222         String value = getStringAttrNS(elem, nsuri, localName);
223
224         boolean result;
225         try{
226             result = DatatypeConverter.parseBoolean(value);
227         }catch(IllegalArgumentException e){
228             String message = MessageFormat.format(ERRMSG_INVATTR,
229                                                   localName,
230                                                   value );
231             throw new TogaXmlException(message, e);
232         }
233
234         return result;
235     }
236
237     /**
238      * 要素からxsd:integer型属性値を読み取る。
239      * @param elem 要素
240      * @param nsuri 名前空間URI
241      * @param localName 属性名
242      * @return int値
243      * @throws TogaXmlException 属性値が見つからなかった。
244      */
245     public static int getIntegerAttrNS(Element elem,
246                                        String nsuri,
247                                        String localName )
248             throws TogaXmlException{
249         String value = getStringAttrNS(elem, nsuri, localName);
250
251         int result;
252         try{
253             result = DatatypeConverter.parseInt(value);
254         }catch(NumberFormatException e){
255             String message = MessageFormat.format(ERRMSG_INVATTR,
256                                                   localName,
257                                                   value );
258             throw new TogaXmlException(message, e);
259         }
260
261         return result;
262     }
263
264     /**
265      * 要素からxsd:float型属性値を読み取る。
266      * @param elem 要素
267      * @param nsuri 名前空間URI
268      * @param localName 属性名
269      * @return float値
270      * @throws TogaXmlException 属性値が見つからなかった。
271      */
272     public static float getFloatAttrNS(Element elem,
273                                        String nsuri,
274                                        String localName )
275             throws TogaXmlException{
276         String value = getStringAttrNS(elem, nsuri, localName);
277
278         float result;
279         try{
280             result = DatatypeConverter.parseFloat(value);
281         }catch(NumberFormatException e){
282             String message = MessageFormat.format(ERRMSG_INVATTR,
283                                                   localName,
284                                                   value );
285             throw new TogaXmlException(message, e);
286         }
287
288         return result;
289     }
290
291 }