OSDN Git Service

[no commit message]
[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.util.Iterator;
11 import java.util.LinkedList;
12 import java.util.List;
13 import java.util.NoSuchElementException;
14 import org.w3c.dom.Element;
15 import org.w3c.dom.Node;
16
17 /**
18  * DOMユーティリティ。(名前空間対応)
19  *
20  */
21 public class DomNsUtils {
22
23     /**
24      * ノードの名前空間とローカル名を判定する。
25      * @param node ノード
26      * @param nsuri 名前空間URI
27      * @param localName ローカル名
28      * @return ノードの名前空間とローカル名が一致したらtrue
29      */
30     public static boolean hasNsLocalName(Node node,
31                                          String nsuri,
32                                          String localName ){
33         String nodeLocalName = node.getLocalName();
34         String nodeNsUri     = node.getNamespaceURI();
35
36         if( ! localName.equals(nodeLocalName) ) return false;
37         if( ! nsuri.equals(nodeNsUri) )         return false;
38
39         return true;
40     }
41
42     /**
43      * 指定された名前の子要素を1つだけ返す。
44      * @param parent 親要素
45      * @param nsuri 名前空間URI
46      * @param localName 子要素名
47      * @return 子要素
48      * @throws TogaXmlException 1つも見つからなかった
49      */
50     public static Element getChild(Element parent,
51                                    String nsuri,
52                                    String localName )
53             throws TogaXmlException{
54         Element result = null;
55
56         for(Node node = parent.getFirstChild();
57             node != null;
58             node = node.getNextSibling() ){
59
60             if(node.getNodeType() != Node.ELEMENT_NODE) continue;
61             Element elem = (Element) node;
62
63             if(hasNsLocalName(elem, nsuri, localName)){
64                 result = elem;
65                 break;
66             }
67         }
68
69         if(result == null){
70             String message =
71                     "Elem:[" + localName + "] was not found in "
72                     +"Elem:[" + parent.getTagName() + "]";
73             throw new TogaXmlException(message);
74         }
75
76         return result;
77     }
78
79     /**
80      * 親要素が指定された名前の子要素を持つか判定する。
81      * @param parent 親要素
82      * @param nsuri 名前空間URI
83      * @param localName 子要素名
84      * @return 指定名の子要素が存在すればtrue
85      */
86     public static boolean hasChild(Element parent,
87                                    String nsuri,
88                                    String localName ){
89         for(Node node = parent.getFirstChild();
90             node != null;
91             node = node.getNextSibling() ){
92
93             if(node.getNodeType() != Node.ELEMENT_NODE) continue;
94             Element elem = (Element) node;
95
96             if(hasNsLocalName(elem, nsuri, localName)){
97                 return true;
98             }
99         }
100
101         return false;
102     }
103
104     /**
105      * 指定された名前の子要素のリストを返す。
106      * @param parent 親要素
107      * @param nsuri 名前空間URI
108      * @param localName 子要素名
109      * @return 子要素のリスト
110      */
111     public static List<Element> getChildList(Element parent,
112                                              String nsuri,
113                                              String localName ){
114         List<Element> result = new LinkedList<Element>();
115
116         for(Node node = parent.getFirstChild();
117             node != null;
118             node = node.getNextSibling() ){
119
120             if(node.getNodeType() != Node.ELEMENT_NODE) continue;
121             Element elem = (Element) node;
122
123             if(hasNsLocalName(elem, nsuri, localName)){
124                 result.add(elem);
125             }
126         }
127
128         return result;
129     }
130
131     /**
132      * 指定された名前の子要素の列挙子を返す。
133      * @param parent 親要素
134      * @param nsuri 名前空間URI
135      * @param localName 子要素名
136      * @return 子要素の列挙子
137      */
138     public static Iterator<Element> getChildIterator(Element parent,
139                                                      String nsuri,
140                                                      String localName ){
141         Element firstElem;
142         try{
143             firstElem = getChild(parent, nsuri, localName);
144         }catch(TogaXmlException e){
145             firstElem = null;
146         }
147
148         Iterator<Element> result = new ElemIterator(firstElem);
149
150         return result;
151     }
152
153     /**
154      * 指定された名前の子要素のforeachを返す。
155      * @param parent 親要素
156      * @param nsuri 名前空間URI
157      * @param localName 子要素名
158      * @return 子要素のforeach
159      */
160     public static Iterable<Element> getEachChild(Element parent,
161                                                  String nsuri,
162                                                  String localName ){
163         final Iterator<Element> iterator =
164                 getChildIterator(parent, nsuri, localName);
165         Iterable<Element> result = new Iterable<Element>(){
166             @Override
167             public Iterator<Element> iterator(){
168                 return iterator;
169             }
170         };
171         return result;
172     }
173
174     /**
175      * 同じ名前空間とローカル名を持つ次の要素を返す。
176      * @param elem 要素
177      * @return 次の要素。なければnull
178      */
179     public static Element nextNamedElement(Element elem){
180         String nsuri = elem.getNamespaceURI();
181         String localName = elem.getLocalName();
182         Element nextElem = elem;
183         for(;;){
184             nextElem = DomUtils.nextElement(nextElem);
185             if(nextElem == null) break;
186             if(hasNsLocalName(nextElem, nsuri, localName)) break;
187         }
188
189         return nextElem;
190     }
191
192
193     /**
194      * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。
195      */
196     private static class ElemIterator implements Iterator<Element>{
197         private Element next;
198
199         /**
200          * コンストラクタ。
201          * @param elem 最初の要素。nullを指定すれば空列挙子となる。
202          */
203         private ElemIterator(Element elem){
204             super();
205             this.next = elem;
206         }
207
208         /**
209          * {@inheritDoc}
210          * @return {@inheritDoc}
211          */
212         @Override
213         public boolean hasNext(){
214             if(this.next == null) return false;
215             return true;
216         }
217
218         /**
219          * {@inheritDoc}
220          * @return {@inheritDoc}
221          * @throws NoSuchElementException {@inheritDoc}
222          */
223         @Override
224         public Element next() throws NoSuchElementException{
225             if(this.next == null) throw new NoSuchElementException();
226             Element result = this.next;
227             this.next = nextNamedElement(this.next);
228             return result;
229         }
230
231         /**
232          * {@inheritDoc}
233          * ※ 未サポート。
234          */
235         @Override
236         public void remove(){
237             throw new UnsupportedOperationException();
238         }
239
240     }
241
242 }