OSDN Git Service

XML名前空間対応
[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         boolean needLocalCmp =
56                 localName != null;
57         boolean needUriCmp =
58                 nsuri != null && nodeNsUri != null;
59
60         if(needLocalCmp && ! localName.equals(nodeLocalName) ) return false;
61         if(needUriCmp   && ! nsuri.equals(nodeNsUri))          return false;
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 最初の直下子要素。見つからなければnull。
87      */
88     public static Element pickFirstChild(Node parent,
89                                          String nsuri,
90                                          String localName ){
91         Node node = parent.getFirstChild();
92         while(node != null){
93             if(hasNsLocalNameElem(node, nsuri, localName)){
94                 break;
95             }
96             node = node.getNextSibling();
97         }
98         return (Element) node;
99     }
100
101     /**
102      * 指定された名前空間とローカル名に合致する最初の直下子要素を返す。
103      * <p>見つからなければ例外を投げる。
104      * @param parent 親要素
105      * @param nsuri 名前空間URI
106      * @param localName ローカル名
107      * @return 最初の直下子要素。
108      * @throws TogaXmlException 1つも見つからなかった
109      */
110     public static Element getFirstChild(Element parent,
111                                         String nsuri,
112                                         String localName )
113             throws TogaXmlException{
114         Element elem = pickFirstChild(parent, nsuri, localName);
115
116         if(elem == null){
117             String message = MessageFormat.format(ERRMSG_NOELEM,
118                                                   localName,
119                                                   parent.getLocalName() );
120             throw new TogaXmlException(message);
121         }
122
123         return elem;
124     }
125
126     /**
127      * 指定された名前の子要素のforeachを返す。
128      * @param parent 親要素
129      * @param nsuri 名前空間URI
130      * @param localName 子要素名
131      * @return 子要素のforeach
132      */
133     public static Iterable<Element> getEachChild(final Element parent,
134                                                  final String nsuri,
135                                                  final String localName ){
136         Iterable<Element> result = new Iterable<Element>(){
137             @Override
138             public Iterator<Element> iterator(){
139                 return new SiblingElemIterator(parent, nsuri, localName);
140             }
141         };
142         return result;
143     }
144
145     /**
146      * 要素に属性が存在するか判定する。
147      * @param elem 要素
148      * @param nsuri 名前空間URI
149      * @param localName ローカル名
150      * @return 存在するならtrue
151      */
152     public static boolean hasAttrNS(Element elem,
153                                     String nsuri,
154                                     String localName ){
155         return elem.hasAttributeNS(nsuri, localName);
156     }
157
158     /**
159      * 要素からxsd:string型属性値を読み取る。
160      * @param elem 要素
161      * @param nsuri 名前空間URI
162      * @param localName 属性名
163      * @return 文字列
164      * @throws TogaXmlException 属性値が見つからなかった。
165      */
166     public static String getStringAttrNS(Element elem,
167                                          String nsuri,
168                                          String localName )
169             throws TogaXmlException{
170         if( ! hasAttrNS(elem, nsuri, localName) ){
171             String message = MessageFormat.format(ERRMSG_NOATTR,
172                                                   localName,
173                                                   elem.getLocalName() );
174             throw new TogaXmlException(message);
175         }
176
177         String result;
178         try{
179             result = elem.getAttributeNS(nsuri, localName);
180         }catch(DOMException e){
181             assert false;
182             throw new AssertionError(e);
183         }
184
185         return result;
186     }
187
188     /**
189      * 要素からxsd:boolean型属性値を読み取る。
190      * @param elem 要素
191      * @param nsuri 名前空間URI
192      * @param localName 属性名
193      * @return 真ならtrue
194      * @throws TogaXmlException 属性値が見つからなかった。
195      */
196     public static boolean getBooleanAttrNS(Element elem,
197                                            String nsuri,
198                                            String localName )
199             throws TogaXmlException{
200         String value = getStringAttrNS(elem, nsuri, localName);
201
202         boolean result;
203         try{
204             result = DatatypeConverter.parseBoolean(value);
205         }catch(IllegalArgumentException e){
206             String message = MessageFormat.format(ERRMSG_INVATTR,
207                                                   localName,
208                                                   value );
209             throw new TogaXmlException(message, e);
210         }
211
212         return result;
213     }
214
215     /**
216      * 要素からxsd:integer型属性値を読み取る。
217      * @param elem 要素
218      * @param nsuri 名前空間URI
219      * @param localName 属性名
220      * @return int値
221      * @throws TogaXmlException 属性値が見つからなかった。
222      */
223     public static int getIntegerAttrNS(Element elem,
224                                        String nsuri,
225                                        String localName )
226             throws TogaXmlException{
227         String value = getStringAttrNS(elem, nsuri, localName);
228
229         int result;
230         try{
231             result = DatatypeConverter.parseInt(value);
232         }catch(NumberFormatException e){
233             String message = MessageFormat.format(ERRMSG_INVATTR,
234                                                   localName,
235                                                   value );
236             throw new TogaXmlException(message, e);
237         }
238
239         return result;
240     }
241
242     /**
243      * 要素からxsd:float型属性値を読み取る。
244      * @param elem 要素
245      * @param nsuri 名前空間URI
246      * @param localName 属性名
247      * @return float値
248      * @throws TogaXmlException 属性値が見つからなかった。
249      */
250     public static float getFloatAttrNS(Element elem,
251                                        String nsuri,
252                                        String localName )
253             throws TogaXmlException{
254         String value = getStringAttrNS(elem, nsuri, localName);
255
256         float result;
257         try{
258             result = DatatypeConverter.parseFloat(value);
259         }catch(NumberFormatException e){
260             String message = MessageFormat.format(ERRMSG_INVATTR,
261                                                   localName,
262                                                   value );
263             throw new TogaXmlException(message, e);
264         }
265
266         return result;
267     }
268
269 }