OSDN Git Service

リポジトリ内改行コードのLFへの修正
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / util / XMLUtilities.java
1 package charactermanaj.util;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.ArrayList;
6 import java.util.Iterator;
7 import java.util.NoSuchElementException;
8
9 import javax.xml.parsers.DocumentBuilder;
10 import javax.xml.parsers.DocumentBuilderFactory;
11 import javax.xml.parsers.ParserConfigurationException;
12
13 import org.w3c.dom.Document;
14 import org.w3c.dom.Element;
15 import org.w3c.dom.Node;
16 import org.w3c.dom.NodeList;
17 import org.xml.sax.ErrorHandler;
18 import org.xml.sax.SAXException;
19 import org.xml.sax.SAXParseException;
20
21 /**
22  * XML用のユーテリティ.<br>
23  * 
24  * @author seraphy
25  */
26 public final class XMLUtilities {
27
28         /**
29          * プライベートコンストラクタ
30          */
31         private XMLUtilities() {
32                 super();
33         }
34
35         /**
36          * XMLドキュメントをロードして返します. 名前空間を有効とします.
37          * 
38          * @param is
39          *            ロードするXMLドキュメントの入力ストリーム
40          * @return ドキュメント
41          * @throws IOException
42          *             読み込みに失敗した場合
43          */
44         public static Document loadDocument(InputStream is) throws IOException {
45                 Document doc;
46                 try {
47                         DocumentBuilderFactory factory = DocumentBuilderFactory
48                                         .newInstance();
49                         factory.setNamespaceAware(true);
50
51                         DocumentBuilder builder = factory.newDocumentBuilder();
52                         final ArrayList<SAXParseException> errors = new ArrayList<SAXParseException>();
53                         builder.setErrorHandler(new ErrorHandler() {
54                                 public void error(SAXParseException exception)
55                                                 throws SAXException {
56                                         errors.add(exception);
57                                 }
58                                 public void fatalError(SAXParseException exception)
59                                                 throws SAXException {
60                                         errors.add(exception);
61                                 }
62                                 public void warning(SAXParseException exception)
63                                                 throws SAXException {
64                                         errors.add(exception);
65                                 }
66                         });
67
68                         doc = builder.parse(is);
69                         if (errors.size() > 0) {
70                                 throw errors.get(0);
71                         }
72
73                         return doc;
74
75                 } catch (ParserConfigurationException ex) {
76                         throw new RuntimeException("JAXP Configuration Exception.", ex);
77
78                 } catch (SAXException ex) {
79                         IOException ex2 = new IOException("xml read failed.");
80                         ex2.initCause(ex);
81                         throw ex2;
82                 }
83         }
84
85         /**
86          * 指定した名前の子要素で、lang属性が一致するものの値を返す.<br>
87          * langが一致するものがない場合は最初の要素の値を返す.<br>
88          * 一つも要素がない場合はnullを返す.
89          * 
90          * @param parent
91          *            親要素
92          * @param elementName
93          *            子要素の名前
94          * @param lang
95          *            言語属性
96          * @return 言語属性が一致する子要素の値、もしくは最初の子要素の値、もしくはnull
97          */
98         public static String getLocalizedElementText(Element parent,
99                         String elementName, String lang) {
100                 String text = null;
101                 for (Element childelm : getChildElements(parent, elementName)) {
102                         String val = childelm.getTextContent();
103
104                         // 最初の定義をデフォルト値として用いる.
105                         if (text == null) {
106                                 text = val;
107                         }
108
109                         // lang指定が一致すれば、それを優先する.
110                         String langNm = childelm.getAttributeNS(
111                                         "http://www.w3.org/XML/1998/namespace", "lang");
112                         if (lang.equals(langNm) && val.length() > 0) {
113                                 text = val;
114                                 break;
115                         }
116                 }
117                 return text;
118         }
119
120         /**
121          * 指定した名前の子要素の最初の値を返す.
122          * 
123          * @param parent
124          *            親要素
125          * @param elementName
126          *            子要素の名前
127          * @return 値、要素がなければnull
128          */
129         public static String getElementText(Element parent, String elementName) {
130                 for (Element childelm : getChildElements(parent, elementName)) {
131                         return childelm.getTextContent();
132                 }
133                 return null;
134         }
135
136         /**
137          * 指定した名前の最初の子要素を返す. なければnull.
138          * 
139          * @param parent
140          *            親要素
141          * @param name
142          *            子要素の名前
143          * @return 最初の子要素、もしくはnull
144          */
145         public static Element getFirstChildElement(Element parent, final String name) {
146                 for (Element elm : getChildElements(parent, name)) {
147                         return elm;
148                 }
149                 return null;
150         }
151
152         /**
153          * 指定した名前の子要素の列挙子を返す. nullの場合は、すべての子要素を返す.
154          * 
155          * @param elm
156          *            親要素
157          * @param name
158          *            子要素の名前、もしくはnull
159          * @return 子要素の列挙子、該当がない場合は空の列挙子が返される
160          */
161         public static Iterable<Element> getChildElements(Element elm,
162                         final String name) {
163                 return iterable(elm.getChildNodes(), new Filter() {
164                         public boolean isAccept(Node node) {
165                                 if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
166                                         if (name == null || name.equals(node.getNodeName())) {
167                                                 return true;
168                                         }
169                                 }
170                                 return false;
171                         }
172                 });
173         }
174
175         /**
176          * すべての子ノードを列挙子として返す
177          * 
178          * @param nodeList
179          * @return
180          */
181         public static <T extends Node> Iterable<T> iterable(final NodeList nodeList) {
182                 return iterable(nodeList, null);
183         }
184
185         /**
186          * フィルタ
187          */
188         public interface Filter {
189                 boolean isAccept(Node node);
190         }
191
192         /**
193          * 指定したノードリストからフィルタ条件にマッチするものだけを列挙子として返す.
194          * 
195          * @param nodeList
196          *            ノードリスト、nullの場合は空とみなす
197          * @param filter
198          *            フィルタ条件、nullの場合はすべて合致とみなす
199          * @return 合致するものだけを列挙する列挙子
200          */
201         public static <T extends Node> Iterable<T> iterable(
202                         final NodeList nodeList, final Filter filter) {
203                 final int mx;
204                 if (nodeList == null) {
205                         mx = 0;
206                 } else {
207                         mx = nodeList.getLength();
208                 }
209                 return new Iterable<T>() {
210                         public Iterator<T> iterator() {
211                                 return new Iterator<T>() {
212                                         private int idx = 0;
213
214                                         private Node nextNode = getNextNode();
215
216                                         private Node getNextNode() {
217                                                 while (idx < mx) {
218                                                         Node node = nodeList.item(idx++);
219                                                         if (filter == null || filter.isAccept(node)) {
220                                                                 return node;
221                                                         }
222                                                 }
223                                                 return null;
224                                         }
225
226                                         public boolean hasNext() {
227                                                 return nextNode != null;
228                                         }
229
230                                         @SuppressWarnings("unchecked")
231                                         public T next() {
232                                                 Node cur = nextNode;
233                                                 if (cur == null) {
234                                                         throw new NoSuchElementException();
235                                                 }
236                                                 nextNode = getNextNode();
237                                                 return (T) cur;
238                                         }
239
240                                         public void remove() {
241                                                 throw new UnsupportedOperationException();
242                                         }
243                                 };
244                         }
245                 };
246         }
247 }