TogaGemは、3D動画制作ツール、MikuMikuDance(MMD)で用いられる各種データファイルを読み書きするためのJavaライブラリです。
旧TogaParserライブラリの資産は、TogaGemライブラリに吸収されました。
Revision | ec69393f6ebc1aebfd4758a16bda221828bc6fac (tree) |
---|---|
Zeit | 2013-06-08 13:30:16 |
Autor | <olyutorskii@user...> |
MMD Ver7.40 対応
@@ -9,6 +9,7 @@ | ||
9 | 9 | ・ジンバルロック判定を甘くした。 |
10 | 10 | ・多言語対応に際してデフォルトロケールへのフォールバックを禁止。 |
11 | 11 | ・コールバックpmdIKInfo()がpmdIKChainInfo()より先に呼ばれるよう変更。 |
12 | + ・MikuMikuDance Ver7.40以降の新VMDファイルフォーマットに対応 | |
12 | 13 | |
13 | 14 | 2.102.2 (2013-03-17) |
14 | 15 | ・Maven3対応。 |
@@ -16,7 +16,7 @@ | ||
16 | 16 | <groupId>jp.sourceforge.mikutoga</groupId> |
17 | 17 | <artifactId>togagem</artifactId> |
18 | 18 | |
19 | - <version>2.102.5-SNAPSHOT</version> | |
19 | + <version>2.102.7-SNAPSHOT</version> | |
20 | 20 | |
21 | 21 | <packaging>jar</packaging> |
22 | 22 | <name>TogaGem</name> |
@@ -37,6 +37,13 @@ | ||
37 | 37 | */ |
38 | 38 | public static final int MORPHNAME_MAX = 15; |
39 | 39 | |
40 | + /** | |
41 | + * IK ON/OFFスイッチ用ボーン名最大長。バイト単位。 | |
42 | + * <p>※MikuMikuDance Ver7.40からの機能。 | |
43 | + * <p>モーション指定用ボーン名と長さが違うので注意。 | |
44 | + */ | |
45 | + public static final int IKSWBONENAME_MAX = 20; | |
46 | + | |
40 | 47 | |
41 | 48 | /** |
42 | 49 | * 隠しコンストラクタ。 |
@@ -0,0 +1,52 @@ | ||
1 | +/* | |
2 | + * VMD boolean info handler | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2013 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.vmd.parser; | |
9 | + | |
10 | +import jp.sfjp.mikutoga.bin.parser.LoopHandler; | |
11 | +import jp.sfjp.mikutoga.bin.parser.MmdFormatException; | |
12 | +import jp.sfjp.mikutoga.bin.parser.ParseStage; | |
13 | + | |
14 | +/** | |
15 | + * VMDモーションファイルの各種ON/OFF情報(モデル表示・IK有効無効) | |
16 | + * の通知用ハンドラ。 | |
17 | + * <p>MikuMikuDance Ver7.40よりVMDファイルに導入された新仕様。 | |
18 | + */ | |
19 | +public interface VmdBoolHandler extends LoopHandler { | |
20 | + | |
21 | + /** モデル表示スイッチ抽出ループ識別子。 */ | |
22 | + ParseStage MODELSIGHT_LIST = new ParseStage(); | |
23 | + | |
24 | + /** IK有効スイッチ抽出ループ識別子。 */ | |
25 | + ParseStage IKSW_LIST = new ParseStage(); | |
26 | + | |
27 | + | |
28 | + /** | |
29 | + * モデルの表示フラグを通知する。 | |
30 | + * <p>{@link #MODELSIGHT_LIST}ループの構成要素。 | |
31 | + * @param show モデルの表示が行われる場合true | |
32 | + * @param keyFrameNo キーフレーム番号 | |
33 | + * @throws MmdFormatException 不正フォーマットによる | |
34 | + * パース処理の中断をパーサに指示 | |
35 | + */ | |
36 | + void vmdModelSight(boolean show, int keyFrameNo) | |
37 | + throws MmdFormatException; | |
38 | + | |
39 | + /** | |
40 | + * IKボーン別のIK処理のON/OFFを通知する。 | |
41 | + * <p>{@link #MODELSIGHT_LIST}ループの下位 | |
42 | + * {@link #IKSW_LIST}ループの構成要素。 | |
43 | + * @param boneName IKボーン名 | |
44 | + * @param validIk IK処理が無効になる場合false | |
45 | + * @param keyFrameNo キーフレーム番号 | |
46 | + * @throws MmdFormatException 不正フォーマットによる | |
47 | + * パース処理の中断をパーサに指示 | |
48 | + */ | |
49 | + void vmdIkSwitch(String boneName, boolean validIk, int keyFrameNo) | |
50 | + throws MmdFormatException; | |
51 | + | |
52 | +} |
@@ -0,0 +1,121 @@ | ||
1 | +/* | |
2 | + * VMD boolean data parser | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2013 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.vmd.parser; | |
9 | + | |
10 | +import java.io.IOException; | |
11 | +import jp.sfjp.mikutoga.bin.parser.BinParser; | |
12 | +import jp.sfjp.mikutoga.bin.parser.MmdFormatException; | |
13 | +import jp.sfjp.mikutoga.bin.parser.ProxyParser; | |
14 | +import jp.sfjp.mikutoga.bin.parser.TextDecoder; | |
15 | +import jp.sfjp.mikutoga.vmd.VmdConst; | |
16 | + | |
17 | +/** | |
18 | + * VMDモーションファイルの各種ON/OFF情報(モデル表示・IK有効無効) | |
19 | + * パーサ。 | |
20 | + * <p>MikuMikuDance Ver7.40以降でサポート | |
21 | + */ | |
22 | +class VmdBoolParser extends ProxyParser { | |
23 | + | |
24 | + private final TextDecoder decoderWin31j = | |
25 | + new TextDecoder(VmdBasicParser.CS_WIN31J); | |
26 | + | |
27 | + private VmdBoolHandler handler = VmdUnifiedHandler.EMPTY; | |
28 | + | |
29 | + | |
30 | + /** | |
31 | + * コンストラクタ。 | |
32 | + * @param parser 委譲先パーサ | |
33 | + */ | |
34 | + VmdBoolParser(BinParser parser){ | |
35 | + super(parser); | |
36 | + this.decoderWin31j.setZeroChopMode(true); | |
37 | + return; | |
38 | + } | |
39 | + | |
40 | + | |
41 | + /** | |
42 | + * ON/OFF情報通知用ハンドラを登録する。 | |
43 | + * @param boolHandler ハンドラ | |
44 | + */ | |
45 | + void setBoolHandler(VmdBoolHandler boolHandler){ | |
46 | + if(boolHandler == null){ | |
47 | + this.handler = VmdUnifiedHandler.EMPTY; | |
48 | + }else{ | |
49 | + this.handler = boolHandler; | |
50 | + } | |
51 | + | |
52 | + return; | |
53 | + } | |
54 | + | |
55 | + /** | |
56 | + * データのパースと通知。 | |
57 | + * @throws IOException IOエラー | |
58 | + * @throws MmdFormatException フォーマットエラー | |
59 | + */ | |
60 | + void parse() throws IOException, MmdFormatException { | |
61 | + if( ! hasMore() ) return; | |
62 | + | |
63 | + parseVmdModelSight(); | |
64 | + | |
65 | + return; | |
66 | + } | |
67 | + | |
68 | + /** | |
69 | + * モデル表示フラグデータのパースと通知。 | |
70 | + * @throws IOException IOエラー | |
71 | + * @throws MmdFormatException フォーマットエラー | |
72 | + */ | |
73 | + private void parseVmdModelSight() | |
74 | + throws IOException, MmdFormatException{ | |
75 | + int modelSightNo = parseLeInt(); | |
76 | + | |
77 | + this.handler.loopStart(VmdBoolHandler.MODELSIGHT_LIST, | |
78 | + modelSightNo ); | |
79 | + | |
80 | + for(int ct = 0; ct < modelSightNo; ct++){ | |
81 | + int keyFrameNo = parseLeInt(); | |
82 | + boolean show = parseBoolean(); | |
83 | + this.handler.vmdModelSight(show, keyFrameNo); | |
84 | + | |
85 | + parseVmdIkSwitch(keyFrameNo); | |
86 | + | |
87 | + this.handler.loopNext(VmdBoolHandler.MODELSIGHT_LIST); | |
88 | + } | |
89 | + | |
90 | + this.handler.loopEnd(VmdBoolHandler.MODELSIGHT_LIST); | |
91 | + | |
92 | + return; | |
93 | + } | |
94 | + | |
95 | + /** | |
96 | + * IK有効スイッチデータのパースと通知。 | |
97 | + * @param keyFrameNo キーフレーム番号 | |
98 | + * @throws IOException IOエラー | |
99 | + * @throws MmdFormatException フォーマットエラー | |
100 | + */ | |
101 | + private void parseVmdIkSwitch(int keyFrameNo) | |
102 | + throws IOException, MmdFormatException{ | |
103 | + int ikSwitchNo = parseLeInt(); | |
104 | + | |
105 | + this.handler.loopStart(VmdBoolHandler.IKSW_LIST, ikSwitchNo); | |
106 | + | |
107 | + for(int ct = 0; ct < ikSwitchNo; ct++){ | |
108 | + String boneName = parseString(this.decoderWin31j, | |
109 | + VmdConst.IKSWBONENAME_MAX ); | |
110 | + boolean valid = parseBoolean(); | |
111 | + this.handler.vmdIkSwitch(boneName, valid, keyFrameNo); | |
112 | + | |
113 | + this.handler.loopNext(VmdBoolHandler.IKSW_LIST); | |
114 | + } | |
115 | + | |
116 | + this.handler.loopEnd(VmdBoolHandler.IKSW_LIST); | |
117 | + | |
118 | + return; | |
119 | + } | |
120 | + | |
121 | +} |
@@ -23,10 +23,10 @@ | ||
23 | 23 | private final VmdBasicParser basicParser; |
24 | 24 | private final VmdCameraParser cameraParser; |
25 | 25 | private final VmdLightingParser lightingParser; |
26 | + private final VmdBoolParser boolParser; | |
26 | 27 | |
27 | 28 | private VmdBasicHandler basicHandler = VmdUnifiedHandler.EMPTY; |
28 | 29 | |
29 | - private boolean ignoreName = true; | |
30 | 30 | private boolean redundantCheck = false; |
31 | 31 | |
32 | 32 |
@@ -46,6 +46,7 @@ | ||
46 | 46 | this.basicParser = new VmdBasicParser(parser); |
47 | 47 | this.cameraParser = new VmdCameraParser(parser); |
48 | 48 | this.lightingParser = new VmdLightingParser(parser); |
49 | + this.boolParser = new VmdBoolParser(parser); | |
49 | 50 | |
50 | 51 | return; |
51 | 52 | } |
@@ -94,15 +95,11 @@ | ||
94 | 95 | } |
95 | 96 | |
96 | 97 | /** |
97 | - * カメラ・ライティングデータのパースを試みるか否かの判断で、 | |
98 | - * 特殊モデル名判定を無視するか否か設定する。 | |
99 | - * デフォルトではモデル名を無視。 | |
100 | - * <p>※MMDVer7.30前後のVMD出力不具合を回避したい場合は、 | |
101 | - * オフにするとパースに成功する場合がある。 | |
102 | - * @param mode モデル名を無視するならtrue | |
98 | + * ON/OFF情報通知用ハンドラを登録する。 | |
99 | + * @param boolHandler ハンドラ | |
103 | 100 | */ |
104 | - public void setIgnoreName(boolean mode){ | |
105 | - this.ignoreName = mode; | |
101 | + public void setBoolHandler(VmdBoolHandler boolHandler){ | |
102 | + this.boolParser.setBoolHandler(boolHandler); | |
106 | 103 | return; |
107 | 104 | } |
108 | 105 |
@@ -111,6 +108,7 @@ | ||
111 | 108 | * デフォルトではチェックを行わない。 |
112 | 109 | * <p>※MMDVer7.30前後のVMD出力不具合を回避したい場合は、 |
113 | 110 | * オフにするとパースに成功する場合がある。 |
111 | + * <p>※MMD Ver7.39x64以降はチェック回避必須。 | |
114 | 112 | * @param mode チェックさせたければtrue |
115 | 113 | */ |
116 | 114 | public void setRedundantCheck(boolean mode){ |
@@ -125,7 +123,6 @@ | ||
125 | 123 | * @throws MmdFormatException フォーマットエラー |
126 | 124 | */ |
127 | 125 | public void parseVmd() throws IOException, MmdFormatException { |
128 | - setIgnoreName(this.ignoreName); | |
129 | 126 | setRedundantCheck(this.redundantCheck); |
130 | 127 | |
131 | 128 | this.basicHandler.vmdParseStart(); |
@@ -140,20 +137,21 @@ | ||
140 | 137 | |
141 | 138 | /** |
142 | 139 | * VMDファイル本体のパースを開始する。 |
143 | - * <p>モデル名がボーンモーション用と推測され、 | |
144 | - * かつパーサがStrict-modeでない場合、 | |
145 | - * カメラ、ライティングデータのパースは行われない。 | |
146 | 140 | * @throws IOException IOエラー |
147 | 141 | * @throws MmdFormatException フォーマットエラー |
148 | 142 | */ |
149 | 143 | private void parseBody() throws IOException, MmdFormatException{ |
150 | 144 | this.basicParser.parse(); |
151 | 145 | |
152 | - if(this.basicParser.hasStageActName() || this.ignoreName){ | |
146 | + if(this.cameraParser.hasMore()){ | |
153 | 147 | this.cameraParser.parse(); |
154 | 148 | this.lightingParser.parse(); |
155 | 149 | } |
156 | 150 | |
151 | + if(this.boolParser.hasMore()){ | |
152 | + this.boolParser.parse(); | |
153 | + } | |
154 | + | |
157 | 155 | return; |
158 | 156 | } |
159 | 157 |
@@ -15,7 +15,8 @@ | ||
15 | 15 | public interface VmdUnifiedHandler |
16 | 16 | extends VmdBasicHandler, |
17 | 17 | VmdCameraHandler, |
18 | - VmdLightingHandler { | |
18 | + VmdLightingHandler, | |
19 | + VmdBoolHandler { | |
19 | 20 | |
20 | 21 | /** 何もしない統合ハンドラ。 */ |
21 | 22 | VmdUnifiedHandler EMPTY = |
@@ -0,0 +1,699 @@ | ||
1 | +/* | |
2 | + * abstract xml exporter | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2013 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import java.io.IOException; | |
11 | +import java.util.regex.Matcher; | |
12 | +import java.util.regex.Pattern; | |
13 | +import javax.xml.bind.DatatypeConverter; | |
14 | + | |
15 | +/** | |
16 | + * Appendable実装に依存したXMLエクスポータの半実装。 | |
17 | + * UCS4は未サポート。 | |
18 | + */ | |
19 | +abstract class AbstractXmlExporter implements XmlExporter{ | |
20 | + | |
21 | + /** デフォルトの改行文字列。 */ | |
22 | + private static final String DEF_NL = "\n"; // 0x0a(LF) | |
23 | + /** デフォルトのインデント単位。 */ | |
24 | + private static final String DEF_INDENT_UNIT = "\u0020\u0020"; // ␣␣ | |
25 | + | |
26 | + private static final char CH_SP = '\u0020'; // ␣ | |
27 | + private static final char CH_YEN = '\u00a5'; // ¥ | |
28 | + private static final char CH_BSLASH = (char)0x005c; // \ | |
29 | + private static final char CH_DQ = '\u0022'; // " | |
30 | + private static final char CH_SQ = (char)0x0027; // ' | |
31 | + private static final char CH_EQ = '='; // = | |
32 | + private static final char CH_LT = '<'; | |
33 | + private static final char CH_GT = '>'; | |
34 | + | |
35 | + private static final String COMM_START = "<!--"; | |
36 | + private static final String COMM_END = "-->"; | |
37 | + | |
38 | + private static final Pattern NUM_FUZZY = | |
39 | + Pattern.compile("([^.]*\\.[0-9][0-9]*?)0+"); | |
40 | + | |
41 | + private static final String REF_HEX = "&#x"; | |
42 | + private static final int HEX_EXP = 4; // 2 ** 4 == 16 | |
43 | + private static final int MASK_1HEX = (1 << HEX_EXP) - 1; // 0b00001111 | |
44 | + private static final int MAX_OCTET = (1 << Byte.SIZE) - 1; // 0xff | |
45 | + private static final char[] HEXCHAR_TABLE = { | |
46 | + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |
47 | + 'A', 'B', 'C', 'D', 'E', 'F', | |
48 | + }; | |
49 | + | |
50 | + static{ | |
51 | + assert HEX_EXP * 2 == Byte.SIZE; | |
52 | + assert HEXCHAR_TABLE.length == (1 << HEX_EXP); | |
53 | + } | |
54 | + | |
55 | + | |
56 | + private boolean basicLatinOnlyOut = true; | |
57 | + private String newline = DEF_NL; | |
58 | + private String indentUnit = DEF_INDENT_UNIT; | |
59 | + private int indentNest = 0; | |
60 | + | |
61 | + | |
62 | + /** | |
63 | + * コンストラクタ。 | |
64 | + */ | |
65 | + protected AbstractXmlExporter(){ | |
66 | + super(); | |
67 | + return; | |
68 | + } | |
69 | + | |
70 | + | |
71 | + /** | |
72 | + * ASCIIコード相当(UCS:Basic-Latin)の文字か否か判定する。 | |
73 | + * <p>※ Basic-Latinには各種制御文字も含まれる。 | |
74 | + * @param ch 判定対象文字 | |
75 | + * @return Basic-Latin文字ならtrue | |
76 | + * <a href="http://www.unicode.org/charts/PDF/U0000.pdf"> | |
77 | + * Unicode 6.2 Controls and Basic Latin | |
78 | + * </a> | |
79 | + */ | |
80 | + protected static boolean isBasicLatin(char ch){ | |
81 | + if('\u0000' <= ch && ch <= '\u007f'){ | |
82 | + return true; | |
83 | + } | |
84 | + return false; | |
85 | + } | |
86 | + | |
87 | + /** | |
88 | + * 冗長な実数出力を抑止する。 | |
89 | + * <p>DatatypeConverterにおけるJDK1.6系と1.7系の仕様変更を吸収する。 | |
90 | + * <p>0.001fは"0.0010"ではなく"0.001"と出力される。 | |
91 | + * <p>指数表記での冗長桁は無視する。 | |
92 | + * @param numTxt 実数表記 | |
93 | + * @return 冗長桁が抑止された実数表記 | |
94 | + * @see javax.xml.bind.DatatypeConverter | |
95 | + */ | |
96 | + protected static String chopFuzzyZero(String numTxt){ | |
97 | + String result; | |
98 | + | |
99 | + Matcher matcher = NUM_FUZZY.matcher(numTxt); | |
100 | + if(matcher.matches()){ | |
101 | + result = matcher.group(1); | |
102 | + }else{ | |
103 | + result = numTxt; | |
104 | + } | |
105 | + | |
106 | + return result; | |
107 | + } | |
108 | + | |
109 | + | |
110 | + /** | |
111 | + * {@inheritDoc} | |
112 | + * @param ch {@inheritDoc} | |
113 | + * @return {@inheritDoc} | |
114 | + * @throws IOException {@inheritDoc} | |
115 | + */ | |
116 | + @Override | |
117 | + public abstract Appendable append(char ch) throws IOException; | |
118 | + | |
119 | + /** | |
120 | + * {@inheritDoc} | |
121 | + * @param seq {@inheritDoc} | |
122 | + * @return {@inheritDoc} | |
123 | + * @throws IOException {@inheritDoc} | |
124 | + */ | |
125 | + @Override | |
126 | + public abstract Appendable append(CharSequence seq) throws IOException; | |
127 | + | |
128 | + /** | |
129 | + * {@inheritDoc} | |
130 | + * @param seq {@inheritDoc} | |
131 | + * @param start {@inheritDoc} | |
132 | + * @param end {@inheritDoc} | |
133 | + * @return {@inheritDoc} | |
134 | + * @throws IOException {@inheritDoc} | |
135 | + */ | |
136 | + @Override | |
137 | + public abstract Appendable append(CharSequence seq, int start, int end) | |
138 | + throws IOException; | |
139 | + | |
140 | + /** | |
141 | + * {@inheritDoc} | |
142 | + * @throws IOException {@inheritDoc} | |
143 | + */ | |
144 | + @Override | |
145 | + public abstract void flush() throws IOException; | |
146 | + | |
147 | + /** | |
148 | + * {@inheritDoc} | |
149 | + * @throws IOException {@inheritDoc} | |
150 | + */ | |
151 | + @Override | |
152 | + public abstract void close() throws IOException; | |
153 | + | |
154 | + | |
155 | + /** | |
156 | + * {@inheritDoc} | |
157 | + * @param ch {@inheritDoc} | |
158 | + * @return {@inheritDoc} | |
159 | + * @throws IOException {@inheritDoc} | |
160 | + */ | |
161 | + @Override | |
162 | + public XmlExporter putRawCh(char ch) throws IOException{ | |
163 | + append(ch); | |
164 | + return this; | |
165 | + } | |
166 | + | |
167 | + /** | |
168 | + * {@inheritDoc} | |
169 | + * @param seq {@inheritDoc} | |
170 | + * @return {@inheritDoc} | |
171 | + * @throws IOException {@inheritDoc} | |
172 | + */ | |
173 | + @Override | |
174 | + public XmlExporter putRawText(CharSequence seq) | |
175 | + throws IOException{ | |
176 | + append(seq); | |
177 | + return this; | |
178 | + } | |
179 | + | |
180 | + /** | |
181 | + * {@inheritDoc} | |
182 | + * @return {@inheritDoc} | |
183 | + * @throws IOException {@inheritDoc} | |
184 | + */ | |
185 | + @Override | |
186 | + public XmlExporter sp() throws IOException{ | |
187 | + putRawCh(CH_SP); | |
188 | + return this; | |
189 | + } | |
190 | + | |
191 | + /** | |
192 | + * {@inheritDoc} | |
193 | + * @param count {@inheritDoc} | |
194 | + * @return {@inheritDoc} | |
195 | + * @throws IOException {@inheritDoc} | |
196 | + */ | |
197 | + @Override | |
198 | + public XmlExporter sp(int count) throws IOException{ | |
199 | + for(int ct = 1; ct <= count; ct++){ | |
200 | + sp(); | |
201 | + } | |
202 | + return this; | |
203 | + } | |
204 | + | |
205 | + /** | |
206 | + * {@inheritDoc} | |
207 | + * @return {@inheritDoc} | |
208 | + */ | |
209 | + @Override | |
210 | + public String getNewLine(){ | |
211 | + return this.newline; | |
212 | + } | |
213 | + | |
214 | + /** | |
215 | + * {@inheritDoc} | |
216 | + * @param newLine {@inheritDoc} | |
217 | + * @throws NullPointerException {@inheritDoc} | |
218 | + */ | |
219 | + @Override | |
220 | + public void setNewLine(String newLine) throws NullPointerException{ | |
221 | + if(newLine == null) throw new NullPointerException(); | |
222 | + this.newline = newLine; | |
223 | + return; | |
224 | + } | |
225 | + | |
226 | + /** | |
227 | + * {@inheritDoc} | |
228 | + * @return {@inheritDoc} | |
229 | + * @throws IOException {@inheritDoc} | |
230 | + */ | |
231 | + @Override | |
232 | + public XmlExporter ln() throws IOException{ | |
233 | + putRawText(getNewLine()); | |
234 | + return this; | |
235 | + } | |
236 | + | |
237 | + /** | |
238 | + * {@inheritDoc} | |
239 | + * @param count {@inheritDoc} | |
240 | + * @return {@inheritDoc} | |
241 | + * @throws IOException {@inheritDoc} | |
242 | + */ | |
243 | + @Override | |
244 | + public XmlExporter ln(int count) throws IOException{ | |
245 | + for(int ct = 1; ct <= count; ct++){ | |
246 | + ln(); | |
247 | + } | |
248 | + return this; | |
249 | + } | |
250 | + | |
251 | + /** | |
252 | + * {@inheritDoc} | |
253 | + * @return {@inheritDoc} | |
254 | + */ | |
255 | + @Override | |
256 | + public String getIndentUnit(){ | |
257 | + return this.indentUnit; | |
258 | + } | |
259 | + | |
260 | + /** | |
261 | + * {@inheritDoc} | |
262 | + * @param indUnit {@inheritDoc} | |
263 | + * @throws NullPointerException {@inheritDoc} | |
264 | + */ | |
265 | + @Override | |
266 | + public void setIndentUnit(String indUnit) throws NullPointerException{ | |
267 | + if(indUnit == null) throw new NullPointerException(); | |
268 | + this.indentUnit = indUnit; | |
269 | + return; | |
270 | + } | |
271 | + | |
272 | + /** | |
273 | + * {@inheritDoc} | |
274 | + */ | |
275 | + @Override | |
276 | + public void pushNest(){ | |
277 | + this.indentNest++; | |
278 | + return; | |
279 | + } | |
280 | + | |
281 | + /** | |
282 | + * {@inheritDoc} | |
283 | + */ | |
284 | + @Override | |
285 | + public void popNest(){ | |
286 | + this.indentNest--; | |
287 | + if(this.indentNest < 0) this.indentNest = 0; | |
288 | + return; | |
289 | + } | |
290 | + | |
291 | + /** | |
292 | + * {@inheritDoc} | |
293 | + * @return {@inheritDoc} | |
294 | + */ | |
295 | + @Override | |
296 | + public int getIndentLevel(){ | |
297 | + return this.indentNest; | |
298 | + } | |
299 | + | |
300 | + /** | |
301 | + * {@inheritDoc} | |
302 | + * @return {@inheritDoc} | |
303 | + * @throws IOException {@inheritDoc} | |
304 | + */ | |
305 | + @Override | |
306 | + public XmlExporter ind() throws IOException{ | |
307 | + int level = getIndentLevel(); | |
308 | + for(int ct = 1; ct <= level; ct++){ | |
309 | + putRawText(getIndentUnit()); | |
310 | + } | |
311 | + return this; | |
312 | + } | |
313 | + | |
314 | + /** | |
315 | + * {@inheritDoc} | |
316 | + * @return {@inheritDoc} | |
317 | + */ | |
318 | + @Override | |
319 | + public boolean isBasicLatinOnlyOut(){ | |
320 | + return this.basicLatinOnlyOut; | |
321 | + } | |
322 | + | |
323 | + /** | |
324 | + * {@inheritDoc} | |
325 | + * @param bool {@inheritDoc} | |
326 | + */ | |
327 | + @Override | |
328 | + public void setBasicLatinOnlyOut(boolean bool){ | |
329 | + this.basicLatinOnlyOut = bool; | |
330 | + return; | |
331 | + } | |
332 | + | |
333 | + /** | |
334 | + * {@inheritDoc} | |
335 | + * @param ch {@inheritDoc} | |
336 | + * @return {@inheritDoc} | |
337 | + * @throws IOException {@inheritDoc} | |
338 | + */ | |
339 | + @Override | |
340 | + public XmlExporter putCharRef2Hex(char ch) throws IOException{ | |
341 | + if(ch > MAX_OCTET) return putCharRef4Hex(ch); | |
342 | + | |
343 | + int ibits = ch; // 常に正なので符号拡張なし | |
344 | + | |
345 | + int idx4 = ibits & MASK_1HEX; | |
346 | + ibits >>= HEX_EXP; | |
347 | + int idx3 = ibits & MASK_1HEX; | |
348 | + | |
349 | + char hex3 = HEXCHAR_TABLE[idx3]; | |
350 | + char hex4 = HEXCHAR_TABLE[idx4]; | |
351 | + | |
352 | + putRawText(REF_HEX).putRawCh(hex3).putRawCh(hex4) | |
353 | + .putRawCh(';'); | |
354 | + | |
355 | + return this; | |
356 | + } | |
357 | + | |
358 | + /** | |
359 | + * {@inheritDoc} | |
360 | + * @param ch {@inheritDoc} | |
361 | + * @return {@inheritDoc} | |
362 | + * @throws IOException {@inheritDoc} | |
363 | + */ | |
364 | + @Override | |
365 | + public XmlExporter putCharRef4Hex(char ch) throws IOException{ | |
366 | + int ibits = ch; // 常に正なので符号拡張なし | |
367 | + | |
368 | + int idx4 = ibits & MASK_1HEX; | |
369 | + ibits >>= HEX_EXP; | |
370 | + int idx3 = ibits & MASK_1HEX; | |
371 | + ibits >>= HEX_EXP; | |
372 | + int idx2 = ibits & MASK_1HEX; | |
373 | + ibits >>= HEX_EXP; | |
374 | + int idx1 = ibits & MASK_1HEX; | |
375 | + | |
376 | + char hex1 = HEXCHAR_TABLE[idx1]; | |
377 | + char hex2 = HEXCHAR_TABLE[idx2]; | |
378 | + char hex3 = HEXCHAR_TABLE[idx3]; | |
379 | + char hex4 = HEXCHAR_TABLE[idx4]; | |
380 | + | |
381 | + putRawText(REF_HEX).putRawCh(hex1).putRawCh(hex2) | |
382 | + .putRawCh(hex3).putRawCh(hex4) | |
383 | + .putRawCh(';'); | |
384 | + | |
385 | + return this; | |
386 | + } | |
387 | + | |
388 | + /** | |
389 | + * {@inheritDoc} | |
390 | + * @param ch {@inheritDoc} | |
391 | + * @return {@inheritDoc} | |
392 | + * @throws IOException {@inheritDoc} | |
393 | + */ | |
394 | + @Override | |
395 | + public XmlExporter putCh(char ch) throws IOException{ | |
396 | + if(Character.isISOControl(ch)){ | |
397 | + putCharRef2Hex(ch); | |
398 | + return this; | |
399 | + } | |
400 | + | |
401 | + String escTxt; | |
402 | + switch(ch){ | |
403 | + case '&': escTxt = "&"; break; | |
404 | + case CH_LT: escTxt = "<"; break; | |
405 | + case CH_GT: escTxt = ">"; break; | |
406 | + case CH_DQ: escTxt = """; break; | |
407 | + case CH_SQ: escTxt = "'"; break; | |
408 | + default: escTxt = null; break; | |
409 | + } | |
410 | + | |
411 | + if(escTxt != null){ | |
412 | + putRawText(escTxt); | |
413 | + }else{ | |
414 | + putRawCh(ch); | |
415 | + } | |
416 | + | |
417 | + return this; | |
418 | + } | |
419 | + | |
420 | + /** | |
421 | + * {@inheritDoc} | |
422 | + * @param content {@inheritDoc} | |
423 | + * @return {@inheritDoc} | |
424 | + * @throws IOException {@inheritDoc} | |
425 | + */ | |
426 | + @Override | |
427 | + public XmlExporter putContent(CharSequence content) | |
428 | + throws IOException{ | |
429 | + int length = content.length(); | |
430 | + | |
431 | + char prev = '\0'; | |
432 | + for(int pos = 0; pos < length; pos++){ | |
433 | + char ch = content.charAt(pos); | |
434 | + | |
435 | + if( isBasicLatinOnlyOut() && ! isBasicLatin(ch) ){ | |
436 | + putCharRef4Hex(ch); | |
437 | + }else if(ch == CH_YEN){ | |
438 | + putRawCh(CH_BSLASH); | |
439 | + }else if(Character.isSpaceChar(ch)){ | |
440 | + if(ch == CH_SP && prev != CH_SP){ | |
441 | + putRawCh(ch); | |
442 | + }else{ | |
443 | + putCharRef2Hex(ch); | |
444 | + } | |
445 | + }else{ | |
446 | + putCh(ch); | |
447 | + } | |
448 | + | |
449 | + prev = ch; | |
450 | + } | |
451 | + | |
452 | + return this; | |
453 | + } | |
454 | + | |
455 | + /** | |
456 | + * {@inheritDoc} | |
457 | + * @param comment {@inheritDoc} | |
458 | + * @return {@inheritDoc} | |
459 | + * @throws IOException {@inheritDoc} | |
460 | + */ | |
461 | + @Override | |
462 | + public XmlExporter putCommentContent(CharSequence comment) | |
463 | + throws IOException{ | |
464 | + int length = comment.length(); | |
465 | + | |
466 | + char prev = '\0'; | |
467 | + for(int pos = 0; pos < length; pos++){ | |
468 | + char ch = comment.charAt(pos); | |
469 | + | |
470 | + if(ch == '\n'){ | |
471 | + ln(); | |
472 | + }else if('\u0000' <= ch && ch <= '\u001f'){ | |
473 | + putRawCh((char)('\u2400' + ch)); | |
474 | + }else if(ch == '\u007f'){ | |
475 | + putRawCh('\u2421'); | |
476 | + }else if(prev == '-' && ch == '-'){ | |
477 | + sp().putRawCh(ch); | |
478 | + }else{ | |
479 | + putRawCh(ch); | |
480 | + } | |
481 | + | |
482 | + prev = ch; | |
483 | + } | |
484 | + | |
485 | + return this; | |
486 | + } | |
487 | + | |
488 | + /** | |
489 | + * {@inheritDoc} | |
490 | + * @param comment {@inheritDoc} | |
491 | + * @return {@inheritDoc} | |
492 | + * @throws IOException {@inheritDoc} | |
493 | + */ | |
494 | + @Override | |
495 | + public XmlExporter putLineComment(CharSequence comment) | |
496 | + throws IOException{ | |
497 | + putRawText(COMM_START).sp(); | |
498 | + putCommentContent(comment); | |
499 | + sp().putRawText(COMM_END); | |
500 | + return this; | |
501 | + } | |
502 | + | |
503 | + /** | |
504 | + * {@inheritDoc} | |
505 | + * @param comment {@inheritDoc} | |
506 | + * @return {@inheritDoc} | |
507 | + * @throws IOException {@inheritDoc} | |
508 | + */ | |
509 | + @Override | |
510 | + public XmlExporter putBlockComment(CharSequence comment) | |
511 | + throws IOException{ | |
512 | + putRawText(COMM_START).ln(); | |
513 | + | |
514 | + putCommentContent(comment); | |
515 | + | |
516 | + int commentLength = comment.length(); | |
517 | + if(commentLength > 0){ | |
518 | + char lastCh = comment.charAt(commentLength - 1); | |
519 | + if(lastCh != '\n'){ | |
520 | + ln(); | |
521 | + } | |
522 | + } | |
523 | + | |
524 | + putRawText(COMM_END).ln(); | |
525 | + | |
526 | + return this; | |
527 | + } | |
528 | + | |
529 | + /** | |
530 | + * {@inheritDoc} | |
531 | + * @param tagName {@inheritDoc} | |
532 | + * @return {@inheritDoc} | |
533 | + * @throws IOException {@inheritDoc} | |
534 | + */ | |
535 | + @Override | |
536 | + public XmlExporter putOpenSTag(CharSequence tagName) | |
537 | + throws IOException{ | |
538 | + putRawCh(CH_LT); | |
539 | + putRawText(tagName); | |
540 | + return this; | |
541 | + } | |
542 | + | |
543 | + /** | |
544 | + * {@inheritDoc} | |
545 | + * @return {@inheritDoc} | |
546 | + * @throws IOException {@inheritDoc} | |
547 | + */ | |
548 | + @Override | |
549 | + public XmlExporter putCloseSTag() | |
550 | + throws IOException{ | |
551 | + putRawCh(CH_GT); | |
552 | + return this; | |
553 | + } | |
554 | + | |
555 | + /** | |
556 | + * {@inheritDoc} | |
557 | + * @param tagName {@inheritDoc} | |
558 | + * @return {@inheritDoc} | |
559 | + * @throws IOException {@inheritDoc} | |
560 | + */ | |
561 | + @Override | |
562 | + public XmlExporter putSimpleSTag(CharSequence tagName) | |
563 | + throws IOException{ | |
564 | + putRawCh(CH_LT); | |
565 | + putRawText(tagName); | |
566 | + putRawCh(CH_GT); | |
567 | + return this; | |
568 | + } | |
569 | + | |
570 | + /** | |
571 | + * {@inheritDoc} | |
572 | + * @param tagName {@inheritDoc} | |
573 | + * @return {@inheritDoc} | |
574 | + * @throws IOException {@inheritDoc} | |
575 | + */ | |
576 | + @Override | |
577 | + public XmlExporter putETag(CharSequence tagName) | |
578 | + throws IOException{ | |
579 | + putRawText("</"); | |
580 | + putRawText(tagName); | |
581 | + putRawCh(CH_GT); | |
582 | + return this; | |
583 | + } | |
584 | + | |
585 | + /** | |
586 | + * {@inheritDoc} | |
587 | + * @param tagName {@inheritDoc} | |
588 | + * @return {@inheritDoc} | |
589 | + * @throws IOException {@inheritDoc} | |
590 | + */ | |
591 | + @Override | |
592 | + public XmlExporter putSimpleEmpty(CharSequence tagName) | |
593 | + throws IOException{ | |
594 | + putRawCh(CH_LT); | |
595 | + putRawText(tagName).sp(); | |
596 | + putCloseEmpty(); | |
597 | + return this; | |
598 | + } | |
599 | + | |
600 | + /** | |
601 | + * {@inheritDoc} | |
602 | + * @return {@inheritDoc} | |
603 | + * @throws IOException {@inheritDoc} | |
604 | + */ | |
605 | + @Override | |
606 | + public XmlExporter putCloseEmpty() | |
607 | + throws IOException{ | |
608 | + putRawText("/>"); | |
609 | + return this; | |
610 | + } | |
611 | + | |
612 | + /** | |
613 | + * {@inheritDoc} | |
614 | + * @param iVal {@inheritDoc} | |
615 | + * @return {@inheritDoc} | |
616 | + * @throws IOException {@inheritDoc} | |
617 | + */ | |
618 | + @Override | |
619 | + public XmlExporter putXsdInt(int iVal) throws IOException{ | |
620 | + String value = DatatypeConverter.printInt(iVal); | |
621 | + putRawText(value); | |
622 | + return this; | |
623 | + } | |
624 | + | |
625 | + /** | |
626 | + * {@inheritDoc} | |
627 | + * @param fVal {@inheritDoc} | |
628 | + * @return {@inheritDoc} | |
629 | + * @throws IOException {@inheritDoc} | |
630 | + */ | |
631 | + @Override | |
632 | + public XmlExporter putXsdFloat(float fVal) throws IOException{ | |
633 | + String value = DatatypeConverter.printFloat(fVal); | |
634 | + value = chopFuzzyZero(value); | |
635 | + putRawText(value); | |
636 | + return this; | |
637 | + } | |
638 | + | |
639 | + /** | |
640 | + * {@inheritDoc} | |
641 | + * @param attrName {@inheritDoc} | |
642 | + * @param iVal {@inheritDoc} | |
643 | + * @return {@inheritDoc} | |
644 | + * @throws IOException {@inheritDoc} | |
645 | + */ | |
646 | + @Override | |
647 | + public XmlExporter putIntAttr(CharSequence attrName, | |
648 | + int iVal) | |
649 | + throws IOException{ | |
650 | + putRawText(attrName).putRawCh(CH_EQ); | |
651 | + | |
652 | + putRawCh(CH_DQ); | |
653 | + putXsdInt(iVal); | |
654 | + putRawCh(CH_DQ); | |
655 | + | |
656 | + return this; | |
657 | + } | |
658 | + | |
659 | + /** | |
660 | + * {@inheritDoc} | |
661 | + * @param attrName {@inheritDoc} | |
662 | + * @param fVal {@inheritDoc} | |
663 | + * @return {@inheritDoc} | |
664 | + * @throws IOException {@inheritDoc} | |
665 | + */ | |
666 | + @Override | |
667 | + public XmlExporter putFloatAttr(CharSequence attrName, | |
668 | + float fVal) | |
669 | + throws IOException{ | |
670 | + putRawText(attrName).putRawCh(CH_EQ); | |
671 | + | |
672 | + putRawCh(CH_DQ); | |
673 | + putXsdFloat(fVal); | |
674 | + putRawCh(CH_DQ); | |
675 | + | |
676 | + return this; | |
677 | + } | |
678 | + | |
679 | + /** | |
680 | + * {@inheritDoc} | |
681 | + * @param attrName {@inheritDoc} | |
682 | + * @param content {@inheritDoc} | |
683 | + * @return {@inheritDoc} | |
684 | + * @throws IOException {@inheritDoc} | |
685 | + */ | |
686 | + @Override | |
687 | + public XmlExporter putAttr(CharSequence attrName, | |
688 | + CharSequence content) | |
689 | + throws IOException{ | |
690 | + putRawText(attrName).putRawCh(CH_EQ); | |
691 | + | |
692 | + putRawCh(CH_DQ); | |
693 | + putContent(content); | |
694 | + putRawCh(CH_DQ); | |
695 | + | |
696 | + return this; | |
697 | + } | |
698 | + | |
699 | +} |
@@ -0,0 +1,106 @@ | ||
1 | +/* | |
2 | + * basic xml exporter | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2010 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import java.io.Closeable; | |
11 | +import java.io.Flushable; | |
12 | +import java.io.IOException; | |
13 | + | |
14 | +/** | |
15 | + * Appendable用XMLエクスポータ実装。 | |
16 | + */ | |
17 | +public class BasicXmlExporter extends AbstractXmlExporter{ | |
18 | + | |
19 | + private Appendable appendable = null; | |
20 | + | |
21 | + | |
22 | + /** | |
23 | + * コンストラクタ。 | |
24 | + */ | |
25 | + public BasicXmlExporter(){ | |
26 | + super(); | |
27 | + return; | |
28 | + } | |
29 | + | |
30 | + | |
31 | + /** | |
32 | + * 出力先アペンダを指定する。 | |
33 | + * @param app 出力先 | |
34 | + * @throws NullPointerException 引数がnull | |
35 | + */ | |
36 | + public void setAppendable(Appendable app) throws NullPointerException{ | |
37 | + if(app == null) throw new NullPointerException(); | |
38 | + | |
39 | + this.appendable = app; | |
40 | + | |
41 | + return; | |
42 | + } | |
43 | + | |
44 | + /** | |
45 | + * {@inheritDoc} | |
46 | + * @param ch {@inheritDoc} | |
47 | + * @return {@inheritDoc} | |
48 | + * @throws IOException {@inheritDoc} | |
49 | + */ | |
50 | + @Override | |
51 | + public Appendable append(char ch) throws IOException{ | |
52 | + return this.appendable.append(ch); | |
53 | + } | |
54 | + | |
55 | + /** | |
56 | + * {@inheritDoc} | |
57 | + * @param seq {@inheritDoc} | |
58 | + * @return {@inheritDoc} | |
59 | + * @throws IOException {@inheritDoc} | |
60 | + */ | |
61 | + @Override | |
62 | + public Appendable append(CharSequence seq) throws IOException{ | |
63 | + return this.appendable.append(seq); | |
64 | + } | |
65 | + | |
66 | + /** | |
67 | + * {@inheritDoc} | |
68 | + * @param seq {@inheritDoc} | |
69 | + * @param start {@inheritDoc} | |
70 | + * @param end {@inheritDoc} | |
71 | + * @return {@inheritDoc} | |
72 | + * @throws IOException {@inheritDoc} | |
73 | + */ | |
74 | + @Override | |
75 | + public Appendable append(CharSequence seq, int start, int end) | |
76 | + throws IOException{ | |
77 | + return this.appendable.append(seq, start, end); | |
78 | + } | |
79 | + | |
80 | + /** | |
81 | + * {@inheritDoc} | |
82 | + * 可能であれば出力をフラッシュする。 | |
83 | + * @throws IOException {@inheritDoc} | |
84 | + */ | |
85 | + @Override | |
86 | + public void flush() throws IOException{ | |
87 | + if(this.appendable instanceof Flushable){ | |
88 | + ((Flushable)this.appendable).flush(); | |
89 | + } | |
90 | + return; | |
91 | + } | |
92 | + | |
93 | + /** | |
94 | + * {@inheritDoc} | |
95 | + * 可能であれば出力をクローズする。 | |
96 | + * @throws IOException {@inheritDoc} | |
97 | + */ | |
98 | + @Override | |
99 | + public void close() throws IOException{ | |
100 | + if(this.appendable instanceof Closeable){ | |
101 | + ((Closeable)this.appendable).close(); | |
102 | + } | |
103 | + return; | |
104 | + } | |
105 | + | |
106 | +} |
@@ -0,0 +1,63 @@ | ||
1 | +/* | |
2 | + * XML custom error-handler | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2010 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import org.xml.sax.ErrorHandler; | |
11 | +import org.xml.sax.SAXException; | |
12 | +import org.xml.sax.SAXParseException; | |
13 | + | |
14 | +/** | |
15 | + * 自製エラーハンドラ。 | |
16 | + * 例外を渡されれば即投げる。 | |
17 | + */ | |
18 | +public final class BotherHandler implements ErrorHandler{ | |
19 | + | |
20 | + /** | |
21 | + * 唯一のシングルトン。 | |
22 | + */ | |
23 | + public static final ErrorHandler HANDLER = new BotherHandler(); | |
24 | + | |
25 | + /** | |
26 | + * 隠しコンストラクタ。 | |
27 | + */ | |
28 | + private BotherHandler(){ | |
29 | + super(); | |
30 | + return; | |
31 | + } | |
32 | + | |
33 | + /** | |
34 | + * {@inheritDoc} | |
35 | + * @param exception {@inheritDoc} | |
36 | + * @throws SAXException {@inheritDoc} | |
37 | + */ | |
38 | + @Override | |
39 | + public void error(SAXParseException exception) throws SAXException{ | |
40 | + throw exception; | |
41 | + } | |
42 | + | |
43 | + /** | |
44 | + * {@inheritDoc} | |
45 | + * @param exception {@inheritDoc} | |
46 | + * @throws SAXException {@inheritDoc} | |
47 | + */ | |
48 | + @Override | |
49 | + public void fatalError(SAXParseException exception) throws SAXException{ | |
50 | + throw exception; | |
51 | + } | |
52 | + | |
53 | + /** | |
54 | + * {@inheritDoc} | |
55 | + * @param exception {@inheritDoc} | |
56 | + * @throws SAXException {@inheritDoc} | |
57 | + */ | |
58 | + @Override | |
59 | + public void warning(SAXParseException exception) throws SAXException{ | |
60 | + throw exception; | |
61 | + } | |
62 | + | |
63 | +} |
@@ -0,0 +1,291 @@ | ||
1 | +/* | |
2 | + * XML DOM utilities with namespace | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2011 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.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 | +} |
@@ -0,0 +1,363 @@ | ||
1 | +/* | |
2 | + * XML DOM utilities | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2010 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.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 javax.xml.bind.DatatypeConverter; | |
15 | +import org.w3c.dom.Element; | |
16 | +import org.w3c.dom.Node; | |
17 | + | |
18 | +/** | |
19 | + * DOMユーティリティ。 | |
20 | + */ | |
21 | +public final class DomUtils { | |
22 | + | |
23 | + // 構文解析バグ回避。 | |
24 | + private static final char BS_CHAR = (char) 0x005c; | |
25 | + | |
26 | + /** | |
27 | + * 隠しコンストラクタ。 | |
28 | + */ | |
29 | + private DomUtils(){ | |
30 | + super(); | |
31 | + assert false; | |
32 | + throw new AssertionError(); | |
33 | + } | |
34 | + | |
35 | + /** | |
36 | + * 要素からxsd:string型属性値を読み取る。 | |
37 | + * @param elem 要素 | |
38 | + * @param attrName 属性名 | |
39 | + * @return 文字列 | |
40 | + * @throws TogaXmlException 属性値が見つからなかった。 | |
41 | + */ | |
42 | + public static String getStringAttr(Element elem, String attrName) | |
43 | + throws TogaXmlException{ | |
44 | + if( ! elem.hasAttribute(attrName) ){ | |
45 | + String message = "Attr:[" + attrName + "] " | |
46 | + + "was not found in " | |
47 | + + "Elem:[" + elem.getTagName()+"]"; | |
48 | + throw new TogaXmlException(message); | |
49 | + } | |
50 | + | |
51 | + String result; | |
52 | + try{ | |
53 | + result = elem.getAttribute(attrName); | |
54 | + }catch(IllegalArgumentException e){ | |
55 | + String message = "Invalid attribute form [" + attrName + "]"; | |
56 | + throw new TogaXmlException(message, e); | |
57 | + } | |
58 | + | |
59 | + return result; | |
60 | + } | |
61 | + | |
62 | + /** | |
63 | + * 要素からxsd:boolean型属性値を読み取る。 | |
64 | + * @param elem 要素 | |
65 | + * @param attrName 属性名 | |
66 | + * @return 真ならtrue | |
67 | + * @throws TogaXmlException 属性値が見つからなかった。 | |
68 | + */ | |
69 | + public static boolean getBooleanAttr(Element elem, String attrName) | |
70 | + throws TogaXmlException{ | |
71 | + String value = getStringAttr(elem, attrName); | |
72 | + | |
73 | + boolean result; | |
74 | + try{ | |
75 | + result = DatatypeConverter.parseBoolean(value); | |
76 | + }catch(IllegalArgumentException e){ | |
77 | + String message = | |
78 | + "Invalid boolean attribute form " | |
79 | + + "[" + attrName + "][" + value + "]"; | |
80 | + throw new TogaXmlException(message, e); | |
81 | + } | |
82 | + | |
83 | + return result; | |
84 | + } | |
85 | + | |
86 | + /** | |
87 | + * 要素からxsd:integer型属性値を読み取る。 | |
88 | + * @param elem 要素 | |
89 | + * @param attrName 属性名 | |
90 | + * @return int値 | |
91 | + * @throws TogaXmlException 属性値が見つからなかった。 | |
92 | + */ | |
93 | + public static int getIntegerAttr(Element elem, String attrName) | |
94 | + throws TogaXmlException{ | |
95 | + String value = getStringAttr(elem, attrName); | |
96 | + | |
97 | + int result; | |
98 | + try{ | |
99 | + result = DatatypeConverter.parseInt(value); | |
100 | + }catch(IllegalArgumentException e){ | |
101 | + String message = | |
102 | + "Invalid integer attribute form " | |
103 | + + "[" + attrName + "][" + value + "]"; | |
104 | + throw new TogaXmlException(message, e); | |
105 | + } | |
106 | + | |
107 | + return result; | |
108 | + } | |
109 | + | |
110 | + /** | |
111 | + * 要素からxsd:float型属性値を読み取る。 | |
112 | + * @param elem 要素 | |
113 | + * @param attrName 属性名 | |
114 | + * @return float値 | |
115 | + * @throws TogaXmlException 属性値が見つからなかった。 | |
116 | + */ | |
117 | + public static float getFloatAttr(Element elem, String attrName) | |
118 | + throws TogaXmlException{ | |
119 | + String value = getStringAttr(elem, attrName); | |
120 | + | |
121 | + float result; | |
122 | + try{ | |
123 | + result = DatatypeConverter.parseFloat(value); | |
124 | + }catch(IllegalArgumentException e){ | |
125 | + String message = | |
126 | + "Invalid float attribute form " | |
127 | + + "[" + attrName + "][" + value + "]"; | |
128 | + throw new TogaXmlException(message, e); | |
129 | + } | |
130 | + | |
131 | + return result; | |
132 | + } | |
133 | + | |
134 | + /** | |
135 | + * 要素から日本語Windows用ファイル名を属性値として読み取る。 | |
136 | + * 念のため文字U+00A5は文字U-005Cに変換される。 | |
137 | + * @param elem 要素 | |
138 | + * @param attrName 属性名 | |
139 | + * @return ファイル名 | |
140 | + * @throws TogaXmlException 属性値が見つからなかった。 | |
141 | + */ | |
142 | + public static String getSjisFileNameAttr(Element elem, String attrName) | |
143 | + throws TogaXmlException{ | |
144 | + String result; | |
145 | + try{ | |
146 | + result = getStringAttr(elem, attrName); | |
147 | + }catch(IllegalArgumentException e){ | |
148 | + String message = | |
149 | + "Invalid winfile attribute form " | |
150 | + + "[" + attrName + "]"; | |
151 | + throw new TogaXmlException(message, e); | |
152 | + } | |
153 | + | |
154 | + result = result.replace("" + '\u00a5', "" + BS_CHAR); | |
155 | + | |
156 | + return result; | |
157 | + } | |
158 | + | |
159 | + /** | |
160 | + * 指定された名前の子要素を1つだけ返す。 | |
161 | + * @param parent 親要素 | |
162 | + * @param tagName 子要素名 | |
163 | + * @return 子要素 | |
164 | + * @throws TogaXmlException 1つも見つからなかった | |
165 | + */ | |
166 | + public static Element getChild(Element parent, String tagName) | |
167 | + throws TogaXmlException{ | |
168 | + Element result = null; | |
169 | + | |
170 | + for(Node node = parent.getFirstChild(); | |
171 | + node != null; | |
172 | + node = node.getNextSibling() ){ | |
173 | + | |
174 | + if(node.getNodeType() != Node.ELEMENT_NODE) continue; | |
175 | + Element elem = (Element) node; | |
176 | + | |
177 | + String elemTagName = elem.getTagName(); | |
178 | + if( tagName.equals(elemTagName) ){ | |
179 | + result = elem; | |
180 | + break; | |
181 | + } | |
182 | + } | |
183 | + | |
184 | + if(result == null){ | |
185 | + String message = | |
186 | + "Elem:[" + tagName + "] was not found in " | |
187 | + +"Elem:[" + parent.getTagName() + "]"; | |
188 | + throw new TogaXmlException(message); | |
189 | + } | |
190 | + | |
191 | + return result; | |
192 | + } | |
193 | + | |
194 | + /** | |
195 | + * 親要素が指定された名前の子要素を持つか判定する。 | |
196 | + * @param parent 親要素 | |
197 | + * @param tagName 子要素名 | |
198 | + * @return 指定名の子要素が存在すればtrue | |
199 | + */ | |
200 | + public static boolean hasChild(Element parent, String tagName){ | |
201 | + for(Node node = parent.getFirstChild(); | |
202 | + node != null; | |
203 | + node = node.getNextSibling() ){ | |
204 | + | |
205 | + if(node.getNodeType() != Node.ELEMENT_NODE) continue; | |
206 | + Element elem = (Element) node; | |
207 | + | |
208 | + String elemTagName = elem.getTagName(); | |
209 | + if( tagName.equals(elemTagName) ) return true; | |
210 | + } | |
211 | + | |
212 | + return false; | |
213 | + } | |
214 | + | |
215 | + /** | |
216 | + * 指定された名前の子要素のリストを返す。 | |
217 | + * @param parent 親要素 | |
218 | + * @param childTag 子要素名 | |
219 | + * @return 子要素のリスト | |
220 | + */ | |
221 | + public static List<Element> getChildList(Element parent, | |
222 | + String childTag){ | |
223 | + List<Element> result = new LinkedList<Element>(); | |
224 | + | |
225 | + for(Node node = parent.getFirstChild(); | |
226 | + node != null; | |
227 | + node = node.getNextSibling() ){ | |
228 | + | |
229 | + if(node.getNodeType() != Node.ELEMENT_NODE) continue; | |
230 | + Element elem = (Element) node; | |
231 | + | |
232 | + String tagName = elem.getTagName(); | |
233 | + if( ! childTag.equals(tagName) ) continue; | |
234 | + | |
235 | + result.add(elem); | |
236 | + } | |
237 | + | |
238 | + return result; | |
239 | + } | |
240 | + | |
241 | + /** | |
242 | + * 指定された名前の子要素の列挙子を返す。 | |
243 | + * @param parent 親要素 | |
244 | + * @param childTag 子要素名 | |
245 | + * @return 子要素の列挙子 | |
246 | + */ | |
247 | + public static Iterator<Element> getChildIterator(Element parent, | |
248 | + String childTag){ | |
249 | + Element firstElem; | |
250 | + try{ | |
251 | + firstElem = getChild(parent, childTag); | |
252 | + }catch(TogaXmlException e){ | |
253 | + firstElem = null; | |
254 | + } | |
255 | + | |
256 | + Iterator<Element> result = new ElemIterator(firstElem); | |
257 | + | |
258 | + return result; | |
259 | + } | |
260 | + | |
261 | + /** | |
262 | + * 指定された名前の子要素のforeachを返す。 | |
263 | + * @param parent 親要素 | |
264 | + * @param childTag 子要素名 | |
265 | + * @return 子要素のforeach | |
266 | + */ | |
267 | + public static Iterable<Element> getEachChild(Element parent, | |
268 | + String childTag){ | |
269 | + final Iterator<Element> iterator = getChildIterator(parent, childTag); | |
270 | + Iterable<Element> result = new Iterable<Element>(){ | |
271 | + @Override | |
272 | + public Iterator<Element> iterator(){ | |
273 | + return iterator; | |
274 | + } | |
275 | + }; | |
276 | + return result; | |
277 | + } | |
278 | + | |
279 | + /** | |
280 | + * 要素の次の要素を返す。 | |
281 | + * @param elem 要素 | |
282 | + * @return 次の要素。なければnull | |
283 | + */ | |
284 | + public static Element nextElement(Element elem){ | |
285 | + Node nextNode = elem; | |
286 | + for(;;){ | |
287 | + nextNode = nextNode.getNextSibling(); | |
288 | + if(nextNode == null) break; | |
289 | + if(nextNode.getNodeType() == Node.ELEMENT_NODE){ | |
290 | + break; | |
291 | + } | |
292 | + } | |
293 | + | |
294 | + return (Element) nextNode; | |
295 | + } | |
296 | + | |
297 | + /** | |
298 | + * 同じ要素名を持つ次の要素を返す。 | |
299 | + * @param elem 要素 | |
300 | + * @return 次の要素。なければnull | |
301 | + */ | |
302 | + public static Element nextNamedElement(Element elem){ | |
303 | + String tagName = elem.getTagName(); | |
304 | + Element nextElem = elem; | |
305 | + for(;;){ | |
306 | + nextElem = nextElement(nextElem); | |
307 | + if(nextElem == null) break; | |
308 | + if(tagName.equals(nextElem.getTagName())) break; | |
309 | + } | |
310 | + | |
311 | + return nextElem; | |
312 | + } | |
313 | + | |
314 | + /** | |
315 | + * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。 | |
316 | + */ | |
317 | + private static final class ElemIterator implements Iterator<Element> { | |
318 | + private Element next; | |
319 | + | |
320 | + /** | |
321 | + * コンストラクタ。 | |
322 | + * @param elem 最初の要素。nullを指定すれば空列挙子となる。 | |
323 | + */ | |
324 | + ElemIterator(Element elem){ | |
325 | + super(); | |
326 | + this.next = elem; | |
327 | + } | |
328 | + | |
329 | + /** | |
330 | + * {@inheritDoc} | |
331 | + * @return {@inheritDoc} | |
332 | + */ | |
333 | + @Override | |
334 | + public boolean hasNext(){ | |
335 | + if(this.next == null) return false; | |
336 | + return true; | |
337 | + } | |
338 | + | |
339 | + /** | |
340 | + * {@inheritDoc} | |
341 | + * @return {@inheritDoc} | |
342 | + * @throws NoSuchElementException {@inheritDoc} | |
343 | + */ | |
344 | + @Override | |
345 | + public Element next() throws NoSuchElementException{ | |
346 | + if(this.next == null) throw new NoSuchElementException(); | |
347 | + Element result = this.next; | |
348 | + this.next = nextNamedElement(this.next); | |
349 | + return result; | |
350 | + } | |
351 | + | |
352 | + /** | |
353 | + * {@inheritDoc} | |
354 | + * ※ 未サポート。 | |
355 | + */ | |
356 | + @Override | |
357 | + public void remove(){ | |
358 | + throw new UnsupportedOperationException(); | |
359 | + } | |
360 | + | |
361 | + } | |
362 | + | |
363 | +} |
@@ -0,0 +1,31 @@ | ||
1 | +/* | |
2 | + * xml local resource map | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2013 olyutorskii | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import java.net.URI; | |
11 | + | |
12 | +/** | |
13 | + * 代用ローカルリソースの管理を行う。 | |
14 | + * <p>ネットワークを介したグローバルなリソースと、 | |
15 | + * アプリ上のローカルな代用リソースとを対応付ける。 | |
16 | + */ | |
17 | +public interface LocalXmlResource { | |
18 | + | |
19 | + /** | |
20 | + * オリジナル版XMLリソースのURIを返す。 | |
21 | + * @return オリジナル版リソースのURL。 | |
22 | + */ | |
23 | + URI getOriginalResource(); | |
24 | + | |
25 | + /** | |
26 | + * ローカル版XMLリソースのURIを返す。 | |
27 | + * @return ローカル版リソースのURL。 | |
28 | + */ | |
29 | + URI getLocalResource(); | |
30 | + | |
31 | +} |
@@ -0,0 +1,195 @@ | ||
1 | +/* | |
2 | + * proxy xml exporter | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2013 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import java.io.IOException; | |
11 | + | |
12 | +/** | |
13 | + * 委譲型XMLエクスポータ。 | |
14 | + */ | |
15 | +public class ProxyXmlExporter extends AbstractXmlExporter{ | |
16 | + | |
17 | + private final XmlExporter delegate; | |
18 | + | |
19 | + | |
20 | + /** | |
21 | + * コンストラクタ。 | |
22 | + * @param delegate 委譲先 | |
23 | + */ | |
24 | + public ProxyXmlExporter(XmlExporter delegate){ | |
25 | + super(); | |
26 | + this.delegate = delegate; | |
27 | + return; | |
28 | + } | |
29 | + | |
30 | + | |
31 | + /** | |
32 | + * {@inheritDoc} | |
33 | + * @param ch {@inheritDoc} | |
34 | + * @return {@inheritDoc} | |
35 | + * @throws IOException {@inheritDoc} | |
36 | + */ | |
37 | + @Override | |
38 | + public Appendable append(char ch) throws IOException{ | |
39 | + return this.delegate.append(ch); | |
40 | + } | |
41 | + | |
42 | + /** | |
43 | + * {@inheritDoc} | |
44 | + * @param seq {@inheritDoc} | |
45 | + * @return {@inheritDoc} | |
46 | + * @throws IOException {@inheritDoc} | |
47 | + */ | |
48 | + @Override | |
49 | + public Appendable append(CharSequence seq) throws IOException{ | |
50 | + return this.delegate.append(seq); | |
51 | + } | |
52 | + | |
53 | + /** | |
54 | + * {@inheritDoc} | |
55 | + * @param seq {@inheritDoc} | |
56 | + * @param start {@inheritDoc} | |
57 | + * @param end {@inheritDoc} | |
58 | + * @return {@inheritDoc} | |
59 | + * @throws IOException {@inheritDoc} | |
60 | + */ | |
61 | + @Override | |
62 | + public Appendable append(CharSequence seq, int start, int end) | |
63 | + throws IOException{ | |
64 | + return this.delegate.append(seq, start, end); | |
65 | + } | |
66 | + | |
67 | + /** | |
68 | + * {@inheritDoc} | |
69 | + * @throws IOException {@inheritDoc} | |
70 | + */ | |
71 | + @Override | |
72 | + public void flush() throws IOException{ | |
73 | + this.delegate.flush(); | |
74 | + return; | |
75 | + } | |
76 | + | |
77 | + /** | |
78 | + * {@inheritDoc} | |
79 | + * @throws IOException {@inheritDoc} | |
80 | + */ | |
81 | + @Override | |
82 | + public void close() throws IOException{ | |
83 | + this.delegate.close(); | |
84 | + return; | |
85 | + } | |
86 | + | |
87 | + /** | |
88 | + * {@inheritDoc} | |
89 | + * @param ch {@inheritDoc} | |
90 | + * @return {@inheritDoc} | |
91 | + * @throws IOException {@inheritDoc} | |
92 | + */ | |
93 | + @Override | |
94 | + public XmlExporter putRawCh(char ch) throws IOException{ | |
95 | + return this.delegate.putRawCh(ch); | |
96 | + } | |
97 | + | |
98 | + /** | |
99 | + * {@inheritDoc} | |
100 | + * @param seq {@inheritDoc} | |
101 | + * @return {@inheritDoc} | |
102 | + * @throws IOException {@inheritDoc} | |
103 | + */ | |
104 | + @Override | |
105 | + public XmlExporter putRawText(CharSequence seq) throws IOException{ | |
106 | + return this.delegate.putRawText(seq); | |
107 | + } | |
108 | + | |
109 | + /** | |
110 | + * {@inheritDoc} | |
111 | + * @return {@inheritDoc} | |
112 | + */ | |
113 | + @Override | |
114 | + public boolean isBasicLatinOnlyOut(){ | |
115 | + return this.delegate.isBasicLatinOnlyOut(); | |
116 | + } | |
117 | + | |
118 | + /** | |
119 | + * {@inheritDoc} | |
120 | + * @param bool {@inheritDoc} | |
121 | + */ | |
122 | + @Override | |
123 | + public void setBasicLatinOnlyOut(boolean bool){ | |
124 | + this.delegate.setBasicLatinOnlyOut(bool); | |
125 | + return; | |
126 | + } | |
127 | + | |
128 | + /** | |
129 | + * {@inheritDoc} | |
130 | + * @return {@inheritDoc} | |
131 | + */ | |
132 | + @Override | |
133 | + public String getNewLine(){ | |
134 | + return this.delegate.getNewLine(); | |
135 | + } | |
136 | + | |
137 | + /** | |
138 | + * {@inheritDoc} | |
139 | + * @param newLine {@inheritDoc} | |
140 | + * @throws NullPointerException {@inheritDoc} | |
141 | + */ | |
142 | + @Override | |
143 | + public void setNewLine(String newLine) throws NullPointerException{ | |
144 | + this.delegate.setNewLine(newLine); | |
145 | + return; | |
146 | + } | |
147 | + | |
148 | + /** | |
149 | + * {@inheritDoc} | |
150 | + * @return {@inheritDoc} | |
151 | + */ | |
152 | + @Override | |
153 | + public String getIndentUnit(){ | |
154 | + return this.delegate.getIndentUnit(); | |
155 | + } | |
156 | + | |
157 | + /** | |
158 | + * {@inheritDoc} | |
159 | + * @param indUnit {@inheritDoc} | |
160 | + * @throws NullPointerException {@inheritDoc} | |
161 | + */ | |
162 | + @Override | |
163 | + public void setIndentUnit(String indUnit) throws NullPointerException{ | |
164 | + this.delegate.setIndentUnit(indUnit); | |
165 | + return; | |
166 | + } | |
167 | + | |
168 | + /** | |
169 | + * {@inheritDoc} | |
170 | + */ | |
171 | + @Override | |
172 | + public void pushNest(){ | |
173 | + this.delegate.pushNest(); | |
174 | + return; | |
175 | + } | |
176 | + | |
177 | + /** | |
178 | + * {@inheritDoc} | |
179 | + */ | |
180 | + @Override | |
181 | + public void popNest(){ | |
182 | + this.delegate.popNest(); | |
183 | + return; | |
184 | + } | |
185 | + | |
186 | + /** | |
187 | + * {@inheritDoc} | |
188 | + * @return {@inheritDoc} | |
189 | + */ | |
190 | + @Override | |
191 | + public int getIndentLevel(){ | |
192 | + return this.delegate.getIndentLevel(); | |
193 | + } | |
194 | + | |
195 | +} |
@@ -0,0 +1,130 @@ | ||
1 | +/* | |
2 | + * Sax 2 Xsd-types converter | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2013 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import javax.xml.bind.DatatypeConverter; | |
11 | +import org.xml.sax.Attributes; | |
12 | + | |
13 | +/** | |
14 | + * XSD各種型のSAX属性値をJavaプリミティブ型へ変換する。 | |
15 | + */ | |
16 | +public final class SaxAttr { | |
17 | + | |
18 | + /** | |
19 | + * 隠しコンストラクタ。 | |
20 | + */ | |
21 | + private SaxAttr(){ | |
22 | + assert false; | |
23 | + throw new AssertionError(); | |
24 | + } | |
25 | + | |
26 | + | |
27 | + /** | |
28 | + * 属性名に対応する属性値があるか否か判定する。 | |
29 | + * @param attr 属性群 | |
30 | + * @param name 属性名 | |
31 | + * @return 属性名に対応する属性値がある場合はtrue | |
32 | + */ | |
33 | + public static boolean hasAttr(Attributes attr, String name){ | |
34 | + if(attr.getValue(name) == null) return false; | |
35 | + return true; | |
36 | + } | |
37 | + | |
38 | + /** | |
39 | + * xsd:string型属性値の読み込み。 | |
40 | + * @param attr 属性群 | |
41 | + * @param name 属性名 | |
42 | + * @return 属性値。該当する属性が無ければnull。 | |
43 | + */ | |
44 | + public static String getStringAttr(Attributes attr, String name){ | |
45 | + String attrVal = attr.getValue(name); | |
46 | + return attrVal; | |
47 | + } | |
48 | + | |
49 | + /** | |
50 | + * xsd:boolean型属性値の読み込み。 | |
51 | + * @param attr 属性群 | |
52 | + * @param name 属性名 | |
53 | + * @return 属性値。 | |
54 | + * @throws IllegalArgumentException boolean型表記ではない | |
55 | + */ | |
56 | + public static boolean getBooleanAttr(Attributes attr, String name) | |
57 | + throws IllegalArgumentException{ | |
58 | + String attrVal = attr.getValue(name); | |
59 | + boolean bVal; | |
60 | + bVal = DatatypeConverter.parseBoolean(attrVal); | |
61 | + return bVal; | |
62 | + } | |
63 | + | |
64 | + /** | |
65 | + * xsd:boolean型属性値の読み込み。 | |
66 | + * @param attr 属性群 | |
67 | + * @param name 属性名 | |
68 | + * @param def 属性が無い場合のデフォルト値 | |
69 | + * @return 属性値。 | |
70 | + * @throws IllegalArgumentException boolean型表記ではない | |
71 | + */ | |
72 | + public static boolean getBooleanAttr(Attributes attr, | |
73 | + String name, | |
74 | + boolean def ) | |
75 | + throws IllegalArgumentException{ | |
76 | + String attrVal = attr.getValue(name); | |
77 | + if(attrVal == null) return def; | |
78 | + | |
79 | + boolean bVal; | |
80 | + bVal = DatatypeConverter.parseBoolean(attrVal); | |
81 | + | |
82 | + return bVal; | |
83 | + } | |
84 | + | |
85 | + /** | |
86 | + * xsd:byte型属性の読み込み。 | |
87 | + * @param attr 属性群 | |
88 | + * @param name 属性名 | |
89 | + * @return 属性値。 | |
90 | + * @throws NumberFormatException byte型表記ではない | |
91 | + */ | |
92 | + public static byte getByteAttr(Attributes attr, String name) | |
93 | + throws NumberFormatException{ | |
94 | + String attrVal = attr.getValue(name); | |
95 | + byte bVal; | |
96 | + bVal = DatatypeConverter.parseByte(attrVal); | |
97 | + return bVal; | |
98 | + } | |
99 | + | |
100 | + /** | |
101 | + * xsd:float型属性値の読み込み。 | |
102 | + * @param attr 属性群 | |
103 | + * @param name 属性名 | |
104 | + * @return 属性値。 | |
105 | + * @throws NumberFormatException float型表記ではない | |
106 | + */ | |
107 | + public static float getFloatAttr(Attributes attr, String name) | |
108 | + throws NumberFormatException { | |
109 | + String attrVal = attr.getValue(name); | |
110 | + float fVal; | |
111 | + fVal = DatatypeConverter.parseFloat(attrVal); | |
112 | + return fVal; | |
113 | + } | |
114 | + | |
115 | + /** | |
116 | + * xsd:int型属性値の読み込み。 | |
117 | + * @param attr 属性群 | |
118 | + * @param name 属性名 | |
119 | + * @return 属性値。 | |
120 | + * @throws NumberFormatException int型表記ではない | |
121 | + */ | |
122 | + public static int getIntAttr(Attributes attr, String name) | |
123 | + throws NumberFormatException { | |
124 | + String attrVal = attr.getValue(name); | |
125 | + int iVal; | |
126 | + iVal = DatatypeConverter.parseInt(attrVal); | |
127 | + return iVal; | |
128 | + } | |
129 | + | |
130 | +} |
@@ -0,0 +1,151 @@ | ||
1 | +/* | |
2 | + * xml schema utility | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2013 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import java.io.BufferedInputStream; | |
11 | +import java.io.IOException; | |
12 | +import java.io.InputStream; | |
13 | +import java.net.MalformedURLException; | |
14 | +import java.net.URI; | |
15 | +import java.net.URL; | |
16 | +import java.util.ArrayList; | |
17 | +import java.util.List; | |
18 | +import javax.xml.XMLConstants; | |
19 | +import javax.xml.transform.Source; | |
20 | +import javax.xml.transform.stream.StreamSource; | |
21 | +import javax.xml.validation.Schema; | |
22 | +import javax.xml.validation.SchemaFactory; | |
23 | +import org.w3c.dom.ls.LSResourceResolver; | |
24 | +import org.xml.sax.SAXException; | |
25 | + | |
26 | +/** | |
27 | + * XMLスキーマの各種ビルダ。 | |
28 | + */ | |
29 | +public final class SchemaUtil { | |
30 | + | |
31 | + /** | |
32 | + * 隠しコンストラクタ。 | |
33 | + */ | |
34 | + private SchemaUtil(){ | |
35 | + assert false; | |
36 | + throw new AssertionError(); | |
37 | + } | |
38 | + | |
39 | + | |
40 | + /** | |
41 | + * XML Schema 用のスキーマファクトリを返す。 | |
42 | + * @return スキーマファクトリ | |
43 | + */ | |
44 | + public static SchemaFactory newSchemaFactory(){ | |
45 | + SchemaFactory result = newSchemaFactory(null); | |
46 | + return result; | |
47 | + } | |
48 | + | |
49 | + /** | |
50 | + * XML Schema 用のスキーマファクトリを返す。 | |
51 | + * @param resolver カスタムリゾルバ。nullも可。 | |
52 | + * @return スキーマファクトリ | |
53 | + */ | |
54 | + public static SchemaFactory newSchemaFactory( | |
55 | + LSResourceResolver resolver ){ | |
56 | + SchemaFactory schemaFactory = | |
57 | + SchemaFactory.newInstance( | |
58 | + XMLConstants.W3C_XML_SCHEMA_NS_URI | |
59 | + ); | |
60 | + | |
61 | +// schemaFactory.setFeature(name, value); | |
62 | +// schemaFactory.setProperty(name, object); | |
63 | + | |
64 | + schemaFactory.setErrorHandler(BotherHandler.HANDLER); | |
65 | + schemaFactory.setResourceResolver(resolver); | |
66 | + | |
67 | + return schemaFactory; | |
68 | + } | |
69 | + | |
70 | + /** | |
71 | + * ローカルリソースをSourceに変換する。 | |
72 | + * @param resource ローカルリソース | |
73 | + * @return XML Source | |
74 | + * @throws MalformedURLException 不正なURI | |
75 | + * @throws IOException オープンエラー | |
76 | + */ | |
77 | + private static Source toLocalSource(LocalXmlResource resource) | |
78 | + throws MalformedURLException, IOException{ | |
79 | + URI localUri = resource.getLocalResource(); | |
80 | + URL localUrl = localUri.toURL(); | |
81 | + | |
82 | + InputStream is = localUrl.openStream(); | |
83 | + is = new BufferedInputStream(is); | |
84 | + | |
85 | + Source result = new StreamSource(is); | |
86 | + return result; | |
87 | + } | |
88 | + | |
89 | + /** | |
90 | + * ローカルリソース群をSource群に変換する。 | |
91 | + * @param resArray ローカルリソースURI並び | |
92 | + * @return XML Source並び | |
93 | + * @throws MalformedURLException 不正なURI | |
94 | + * @throws IOException オープンエラー | |
95 | + */ | |
96 | + private static Source[] toLocalSourceArray(LocalXmlResource[] resArray) | |
97 | + throws MalformedURLException, IOException{ | |
98 | + List<Source> sourceList = new ArrayList<Source>(resArray.length); | |
99 | + | |
100 | + for(LocalXmlResource resource : resArray){ | |
101 | + Source localSource = toLocalSource(resource); | |
102 | + sourceList.add(localSource); | |
103 | + } | |
104 | + | |
105 | + Source[] result = new Source[sourceList.size()]; | |
106 | + result = sourceList.toArray(result); | |
107 | + return result; | |
108 | + } | |
109 | + | |
110 | + /** | |
111 | + * ローカルスキーマをロードする。 | |
112 | + * <p>任意のリゾルバを指定可能 | |
113 | + * @param resolver リゾルバ | |
114 | + * @param resArray ローカルスキーマ情報並び | |
115 | + * @return スキーマ | |
116 | + */ | |
117 | + public static Schema newSchema(XmlResourceResolver resolver, | |
118 | + LocalXmlResource... resArray ){ | |
119 | + for(LocalXmlResource resource : resArray){ | |
120 | + resolver.putRedirected(resource); | |
121 | + } | |
122 | + | |
123 | + Source[] sources; | |
124 | + try{ | |
125 | + sources = toLocalSourceArray(resArray); | |
126 | + }catch(IOException e){ // ビルド障害 | |
127 | + assert false; | |
128 | + throw new AssertionError(e); | |
129 | + } | |
130 | + | |
131 | + SchemaFactory schemaFactory = newSchemaFactory(resolver); | |
132 | + | |
133 | + Schema result; | |
134 | + try{ | |
135 | + if(sources.length <= 0){ | |
136 | + // ドキュメント埋め込みスキーマURLにリゾルバ経由でアクセス | |
137 | + result = schemaFactory.newSchema(); | |
138 | + }else{ | |
139 | + result = schemaFactory.newSchema(sources); | |
140 | + } | |
141 | + }catch(SAXException e){ // Build error | |
142 | + assert false; | |
143 | + throw new AssertionError(e); | |
144 | + } | |
145 | + | |
146 | + // TODO: Sourceを閉めるのは誰の責務? | |
147 | + | |
148 | + return result; | |
149 | + } | |
150 | + | |
151 | +} |
@@ -0,0 +1,126 @@ | ||
1 | +/* | |
2 | + * sibling element iterator on DOM tree | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2011 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import java.util.Iterator; | |
11 | +import java.util.NoSuchElementException; | |
12 | +import org.w3c.dom.Element; | |
13 | +import org.w3c.dom.Node; | |
14 | + | |
15 | +/** | |
16 | + * 兄弟要素間用Iterator。 | |
17 | + * <p>同じ親と名前空間とローカル名を持つ要素同士を「兄弟要素」とする。 | |
18 | + * <p>ノードの持つ名前空間がnullの場合、全ての名前空間引数にマッチする。 | |
19 | + * <p>削除操作は未サポート。 | |
20 | + */ | |
21 | +public class SiblingElemIterator implements Iterator<Element> { | |
22 | + | |
23 | + private Element next; | |
24 | + private final String nsuri; | |
25 | + private final String localName; | |
26 | + | |
27 | + | |
28 | + /** | |
29 | + * コンストラクタ。 | |
30 | + * @param first 最初の兄弟要素。nullだと一度もiterateしない。 | |
31 | + */ | |
32 | + public SiblingElemIterator(Element first){ | |
33 | + super(); | |
34 | + | |
35 | + this.next = first; | |
36 | + | |
37 | + if(this.next == null){ | |
38 | + this.nsuri = null; | |
39 | + this.localName = null; | |
40 | + }else{ | |
41 | + this.nsuri = this.next.getNamespaceURI(); | |
42 | + this.localName = this.next.getLocalName(); | |
43 | + } | |
44 | + | |
45 | + return; | |
46 | + } | |
47 | + | |
48 | + /** | |
49 | + * コンストラクタ。 | |
50 | + * <p>名前空間引数にnullが渡された場合、全ての名前空間にマッチする。 | |
51 | + * <p>ローカル名引数にnullが渡された場合、全てのローカル名にマッチする。 | |
52 | + * @param parent 親要素 | |
53 | + * @param nsuri 子要素の名前空間URI | |
54 | + * @param localName 子要素のローカル名 | |
55 | + */ | |
56 | + public SiblingElemIterator(Element parent, | |
57 | + String nsuri, | |
58 | + String localName ){ | |
59 | + super(); | |
60 | + | |
61 | + this.next = DomNsUtils.pickFirstChild(parent, nsuri, localName); | |
62 | + | |
63 | + if(this.next == null){ | |
64 | + this.nsuri = null; | |
65 | + this.localName = null; | |
66 | + }else{ | |
67 | + this.nsuri = nsuri; | |
68 | + this.localName = localName; | |
69 | + } | |
70 | + | |
71 | + return; | |
72 | + } | |
73 | + | |
74 | + | |
75 | + /** | |
76 | + * {@inheritDoc} | |
77 | + * @return {@inheritDoc} | |
78 | + */ | |
79 | + @Override | |
80 | + public boolean hasNext(){ | |
81 | + if(this.next != null) return true; | |
82 | + return false; | |
83 | + } | |
84 | + | |
85 | + /** | |
86 | + * {@inheritDoc} | |
87 | + * @return {@inheritDoc} | |
88 | + * @throws NoSuchElementException {@inheritDoc} | |
89 | + */ | |
90 | + @Override | |
91 | + public Element next() throws NoSuchElementException { | |
92 | + if(this.next == null) throw new NoSuchElementException(); | |
93 | + | |
94 | + Element result = this.next; | |
95 | + | |
96 | + Node sibNode = result; | |
97 | + do{ | |
98 | + sibNode = sibNode.getNextSibling(); | |
99 | + if(sibNode == null) break; | |
100 | + }while( ! matchElemName(sibNode) ); | |
101 | + this.next = (Element) sibNode; | |
102 | + | |
103 | + return result; | |
104 | + } | |
105 | + | |
106 | + /** | |
107 | + * 兄弟要素にふさわしい名前を持つか判定する。 | |
108 | + * @param node 判定対象 | |
109 | + * @return 兄弟にふさわしい名前を持つならtrue | |
110 | + */ | |
111 | + private boolean matchElemName(Node node){ | |
112 | + return DomNsUtils.hasNsLocalNameElem(node, | |
113 | + this.nsuri, this.localName ); | |
114 | + } | |
115 | + | |
116 | + /** | |
117 | + * {@inheritDoc} | |
118 | + * ※削除不可。 | |
119 | + * @throws UnsupportedOperationException 削除を試みたので失敗した | |
120 | + */ | |
121 | + @Override | |
122 | + public void remove() throws UnsupportedOperationException { | |
123 | + throw new UnsupportedOperationException(); | |
124 | + } | |
125 | + | |
126 | +} |
@@ -0,0 +1,52 @@ | ||
1 | +/* | |
2 | + * exception about xml | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2010 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +/** | |
11 | + * 意図しないXML文書を検出した際の例外。 | |
12 | + */ | |
13 | +@SuppressWarnings("serial") | |
14 | +public class TogaXmlException extends Exception{ | |
15 | + | |
16 | + /** | |
17 | + * コンストラクタ。 | |
18 | + */ | |
19 | + public TogaXmlException(){ | |
20 | + super(); | |
21 | + return; | |
22 | + } | |
23 | + | |
24 | + /** | |
25 | + * コンストラクタ。 | |
26 | + * @param message メッセージ | |
27 | + */ | |
28 | + public TogaXmlException(String message){ | |
29 | + super(message); | |
30 | + return; | |
31 | + } | |
32 | + | |
33 | + /** | |
34 | + * コンストラクタ。 | |
35 | + * @param message メッセージ | |
36 | + * @param cause 原因の例外 | |
37 | + */ | |
38 | + public TogaXmlException(String message, Throwable cause){ | |
39 | + super(message, cause); | |
40 | + return; | |
41 | + } | |
42 | + | |
43 | + /** | |
44 | + * コンストラクタ。 | |
45 | + * @param cause 原因の例外 | |
46 | + */ | |
47 | + public TogaXmlException(Throwable cause){ | |
48 | + super(cause); | |
49 | + return; | |
50 | + } | |
51 | + | |
52 | +} |
@@ -0,0 +1,318 @@ | ||
1 | +/* | |
2 | + * xml exporter | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2013 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import java.io.Closeable; | |
11 | +import java.io.Flushable; | |
12 | +import java.io.IOException; | |
13 | + | |
14 | +/** | |
15 | + * XMLエクスポータ基本機能のセット。 | |
16 | + */ | |
17 | +public interface XmlExporter extends Appendable, Flushable, Closeable{ | |
18 | + | |
19 | + /** | |
20 | + * 1文字を生出力する。 | |
21 | + * @param ch 文字 | |
22 | + * @return this本体 | |
23 | + * @throws IOException 出力エラー | |
24 | + */ | |
25 | + XmlExporter putRawCh(char ch) throws IOException; | |
26 | + | |
27 | + /** | |
28 | + * 文字列を生出力する。 | |
29 | + * @param seq 文字列 | |
30 | + * @return this本体 | |
31 | + * @throws IOException 出力エラー | |
32 | + */ | |
33 | + XmlExporter putRawText(CharSequence seq) throws IOException; | |
34 | + | |
35 | + /** | |
36 | + * 空白を出力する。 | |
37 | + * @return this本体 | |
38 | + * @throws IOException 出力エラー | |
39 | + */ | |
40 | + XmlExporter sp() throws IOException; | |
41 | + | |
42 | + /** | |
43 | + * 空白を指定回数出力する。 | |
44 | + * @param count 空白回数。0以下の場合は何も出力しない。 | |
45 | + * @return this本体 | |
46 | + * @throws IOException 出力エラー | |
47 | + */ | |
48 | + XmlExporter sp(int count) throws IOException; | |
49 | + | |
50 | + /** | |
51 | + * 改行文字列を返す。 | |
52 | + * @return 改行文字列 | |
53 | + */ | |
54 | + String getNewLine(); | |
55 | + | |
56 | + /** | |
57 | + * 改行文字列を設定する。 | |
58 | + * @param newLine 改行文字列 | |
59 | + * @throws NullPointerException 引数がnull | |
60 | + */ | |
61 | + void setNewLine(String newLine) throws NullPointerException; | |
62 | + | |
63 | + /** | |
64 | + * 改行を出力する。 | |
65 | + * @return this本体 | |
66 | + * @throws IOException 出力エラー | |
67 | + */ | |
68 | + XmlExporter ln() throws IOException; | |
69 | + | |
70 | + /** | |
71 | + * 改行を指定回数出力する。 | |
72 | + * @param count 改行回数。0以下の場合は何も出力しない。 | |
73 | + * @return this本体 | |
74 | + * @throws IOException 出力エラー | |
75 | + */ | |
76 | + XmlExporter ln(int count) throws IOException; | |
77 | + | |
78 | + /** | |
79 | + * インデント単位文字列を返す。 | |
80 | + * @return インデント単位文字列 | |
81 | + */ | |
82 | + String getIndentUnit(); | |
83 | + | |
84 | + /** | |
85 | + * インデント単位文字列を設定する。 | |
86 | + * <p>デフォルトでは空白2個。 | |
87 | + * @param indUnit インデント単位文字列。 | |
88 | + * @throws NullPointerException 引数がnull | |
89 | + */ | |
90 | + void setIndentUnit(String indUnit) throws NullPointerException; | |
91 | + | |
92 | + /** | |
93 | + * インデントレベルを一段下げる。 | |
94 | + */ | |
95 | + void pushNest(); | |
96 | + | |
97 | + /** | |
98 | + * インデントレベルを一段上げる。 | |
99 | + * インデントレベル0の状態をさらに上げようとした場合、何も起こらない。 | |
100 | + */ | |
101 | + void popNest(); | |
102 | + | |
103 | + /** | |
104 | + * インデントレベルを返す。 | |
105 | + * <p>深さ1の場合1を返す。 | |
106 | + * @return インデントレベル | |
107 | + */ | |
108 | + int getIndentLevel(); | |
109 | + | |
110 | + /** | |
111 | + * インデントを出力する。 | |
112 | + * インデント単位文字列をネストレベル回数分出力する。 | |
113 | + * @return this本体 | |
114 | + * @throws IOException 出力エラー | |
115 | + */ | |
116 | + XmlExporter ind() throws IOException; | |
117 | + | |
118 | + /** | |
119 | + * BasicLatin文字だけを出力する状態か判定する。 | |
120 | + * <p>コメント部中身は対象外。 | |
121 | + * @return BasicLatin文字だけで出力するならtrue | |
122 | + */ | |
123 | + boolean isBasicLatinOnlyOut(); | |
124 | + | |
125 | + /** | |
126 | + * BasicLatin文字だけで出力するか設定する。 | |
127 | + * <p>BasicLatin以外の文字(≒日本語)を、そのまま出力するか、 | |
128 | + * 文字参照で出力するか、の設定が可能。 | |
129 | + * <p>コメント部中身は対象外。 | |
130 | + * @param bool BasicLatin文字だけで出力するならtrue | |
131 | + */ | |
132 | + void setBasicLatinOnlyOut(boolean bool); | |
133 | + | |
134 | + /** | |
135 | + * 指定された文字を16進2桁の文字参照形式で出力する。 | |
136 | + * <p>「A」は「&#x41;」になる。 | |
137 | + * <p>2桁で出力できない場合(>0x00ff)は4桁で出力する。 | |
138 | + * @param ch 文字 | |
139 | + * @return this本体 | |
140 | + * @throws IOException 出力エラー | |
141 | + * @see <a href="http://www.w3.org/TR/xml11/#NT-CharRef"> | |
142 | + * W3C XML1.1 Character Reference | |
143 | + * </a> | |
144 | + */ | |
145 | + XmlExporter putCharRef2Hex(char ch) throws IOException; | |
146 | + | |
147 | + /** | |
148 | + * 指定された文字を16進4桁の文字参照形式で出力する。 | |
149 | + * <p>「亜」は「&#x4E9C;」になる。 | |
150 | + * <p>UCS4に伴うサロゲートペアは未サポート | |
151 | + * @param ch 文字 | |
152 | + * @return this本体 | |
153 | + * @throws IOException 出力エラー | |
154 | + * @see <a href="http://www.w3.org/TR/xml11/#NT-CharRef"> | |
155 | + * W3C XML1.1 Character Reference | |
156 | + * </a> | |
157 | + */ | |
158 | + XmlExporter putCharRef4Hex(char ch) throws IOException; | |
159 | + | |
160 | + /** | |
161 | + * 要素の中身および属性値中身を出力する。 | |
162 | + * <p>XMLの構文規則を守る上で必要な各種エスケープ処理が行われる。 | |
163 | + * @param ch 文字 | |
164 | + * @return this本体 | |
165 | + * @throws IOException 出力エラー | |
166 | + */ | |
167 | + XmlExporter putCh(char ch) throws IOException; | |
168 | + | |
169 | + /** | |
170 | + * 要素の中身および属性値中身を出力する。 | |
171 | + * <p>必要に応じてXML定義済み実体文字が割り振られた文字、 | |
172 | + * コントロールコード、および非BasicLatin文字がエスケープされる。 | |
173 | + * <p>半角円通貨記号U+00A5はバックスラッシュU+005Cに置換される。 | |
174 | + * <p>連続するスペースU+0020の2文字目以降は文字参照化される。 | |
175 | + * <p>全角スペースその他空白文字は無条件に文字参照化される。 | |
176 | + * @param content 内容 | |
177 | + * @return this本体 | |
178 | + * @throws IOException 出力エラー | |
179 | + */ | |
180 | + XmlExporter putContent(CharSequence content) throws IOException; | |
181 | + | |
182 | + /** | |
183 | + * コメントの内容を出力する。 | |
184 | + * <p>コメント中の'\n'記号出現に伴い、 | |
185 | + * あらかじめ指定された改行文字が出力される。 | |
186 | + * <p>コメント中の'\n'以外のコントロールコードは | |
187 | + * Control Pictures(U+2400〜)で代替される。 | |
188 | + * <p>それ以外の非BasicLatin文字はそのまま出力される。 | |
189 | + * <p>連続するハイフン(-)記号間には強制的にスペースが挿入される。 | |
190 | + * @param comment コメント内容 | |
191 | + * @return this本体 | |
192 | + * @throws IOException 出力エラー | |
193 | + * <a href="http://www.unicode.org/charts/PDF/U2400.pdf"> | |
194 | + * Unicode 6.2 Controll Pictures | |
195 | + * </a> | |
196 | + */ | |
197 | + XmlExporter putCommentContent(CharSequence comment) throws IOException; | |
198 | + | |
199 | + /** | |
200 | + * 1行コメントを出力する。 | |
201 | + * コメント内部の頭及び末尾に空白が1つ挿入される。 | |
202 | + * @param comment コメント内容 | |
203 | + * @return this本体 | |
204 | + * @throws IOException 出力エラー | |
205 | + */ | |
206 | + XmlExporter putLineComment(CharSequence comment) throws IOException; | |
207 | + | |
208 | + /** | |
209 | + * ブロックコメントを出力する。 | |
210 | + * <p>コメント内部の頭の前に改行が出力される。 | |
211 | + * <p>コメント内部の末尾が改行でない場合、改行が挿入される。 | |
212 | + * <p>ブロックコメント末尾は改行で終わる。 | |
213 | + * <p>インデント設定は無視される。 | |
214 | + * @param comment コメント内容 | |
215 | + * @return this本体 | |
216 | + * @throws IOException 出力エラー | |
217 | + */ | |
218 | + XmlExporter putBlockComment(CharSequence comment) throws IOException; | |
219 | + | |
220 | + /** | |
221 | + * 開始タグ開き表記を出力する。 | |
222 | + * @param tagName タグ名 | |
223 | + * @return this本体 | |
224 | + * @throws IOException 出力エラー | |
225 | + */ | |
226 | + XmlExporter putOpenSTag(CharSequence tagName) throws IOException; | |
227 | + | |
228 | + /** | |
229 | + * 開始タグ閉じ表記を出力する。 | |
230 | + * @return this本体 | |
231 | + * @throws IOException 出力エラー | |
232 | + */ | |
233 | + XmlExporter putCloseSTag() throws IOException; | |
234 | + | |
235 | + /** | |
236 | + * 属性の無いシンプルな開始タグ表記を出力する。 | |
237 | + * @param tagName タグ名 | |
238 | + * @return this本体 | |
239 | + * @throws IOException 出力エラー | |
240 | + */ | |
241 | + XmlExporter putSimpleSTag(CharSequence tagName) throws IOException; | |
242 | + | |
243 | + /** | |
244 | + * 終了タグ表記を出力する。 | |
245 | + * @param tagName タグ名 | |
246 | + * @return this本体 | |
247 | + * @throws IOException 出力エラー | |
248 | + */ | |
249 | + XmlExporter putETag(CharSequence tagName) throws IOException; | |
250 | + | |
251 | + /** | |
252 | + * 属性の無い単出タグ表記を出力する。 | |
253 | + * @param tagName タグ名 | |
254 | + * @return this本体 | |
255 | + * @throws IOException 出力エラー | |
256 | + */ | |
257 | + XmlExporter putSimpleEmpty(CharSequence tagName) throws IOException; | |
258 | + | |
259 | + /** | |
260 | + * 単出タグ閉じ表記を出力する。 | |
261 | + * @return this本体 | |
262 | + * @throws IOException 出力エラー | |
263 | + */ | |
264 | + XmlExporter putCloseEmpty() throws IOException; | |
265 | + | |
266 | + /** | |
267 | + * xsd:int値をXMLスキーマ準拠の形式で出力する。 | |
268 | + * @param iVal int値 | |
269 | + * @return this本体 | |
270 | + * @throws IOException 出力エラー | |
271 | + * @see <a href="http://www.w3.org/TR/xmlschema11-2/#int"> | |
272 | + * XML Schema 1.1 Datatypes int | |
273 | + * </a> | |
274 | + */ | |
275 | + XmlExporter putXsdInt(int iVal) throws IOException; | |
276 | + | |
277 | + /** | |
278 | + * xsd:float値をXMLスキーマ準拠の形式で出力する。 | |
279 | + * @param fVal float値 | |
280 | + * @return this本体 | |
281 | + * @throws IOException 出力エラー | |
282 | + * @see <a href="http://www.w3.org/TR/xmlschema11-2/#sec-lex-float"> | |
283 | + * XML Schema 1.1 Datatypes float Lexical Mapping | |
284 | + * </a> | |
285 | + */ | |
286 | + XmlExporter putXsdFloat(float fVal) throws IOException; | |
287 | + | |
288 | + /** | |
289 | + * int型属性値を出力する。 | |
290 | + * @param attrName 属性名 | |
291 | + * @param iVal int値 | |
292 | + * @return this本体 | |
293 | + * @throws IOException 出力エラー | |
294 | + */ | |
295 | + XmlExporter putIntAttr(CharSequence attrName, int iVal) | |
296 | + throws IOException; | |
297 | + | |
298 | + /** | |
299 | + * float型属性値を出力する。 | |
300 | + * @param attrName 属性名 | |
301 | + * @param fVal float値 | |
302 | + * @return this本体 | |
303 | + * @throws IOException 出力エラー | |
304 | + */ | |
305 | + XmlExporter putFloatAttr(CharSequence attrName, float fVal) | |
306 | + throws IOException; | |
307 | + | |
308 | + /** | |
309 | + * 属性値を出力する。 | |
310 | + * @param attrName 属性名 | |
311 | + * @param content 属性内容 | |
312 | + * @return this本体 | |
313 | + * @throws IOException 出力エラー | |
314 | + */ | |
315 | + XmlExporter putAttr(CharSequence attrName, CharSequence content) | |
316 | + throws IOException; | |
317 | + | |
318 | +} |
@@ -0,0 +1,472 @@ | ||
1 | +/* | |
2 | + * xml resource resolver | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2009 olyutorskii | |
6 | + */ | |
7 | + | |
8 | +package jp.sfjp.mikutoga.xml; | |
9 | + | |
10 | +import java.io.IOException; | |
11 | +import java.io.InputStream; | |
12 | +import java.io.Reader; | |
13 | +import java.net.URI; | |
14 | +import java.net.URISyntaxException; | |
15 | +import java.net.URL; | |
16 | +import java.util.Collections; | |
17 | +import java.util.HashMap; | |
18 | +import java.util.Map; | |
19 | +import org.w3c.dom.ls.LSInput; | |
20 | +import org.w3c.dom.ls.LSResourceResolver; | |
21 | +import org.xml.sax.EntityResolver; | |
22 | +import org.xml.sax.InputSource; | |
23 | +import org.xml.sax.SAXException; | |
24 | + | |
25 | +/** | |
26 | + * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。 | |
27 | + * 相対URIはこのクラスをベースに解決される。 | |
28 | + * 主な用途は外部スキーマのリソース化など。 | |
29 | + */ | |
30 | +public class XmlResourceResolver | |
31 | + implements LSResourceResolver, EntityResolver { | |
32 | + | |
33 | + /** XML Schema. */ | |
34 | + public static final String SCHEMA_XML = | |
35 | + "http://www.w3.org/2001/xml.xsd"; | |
36 | + | |
37 | + /** XSD名前空間。 */ | |
38 | + public static final String NS_XSD = | |
39 | + "http://www.w3.org/2001/XMLSchema-instance"; | |
40 | + | |
41 | + private static final String LOCAL_SCHEMA_XML = | |
42 | + "resources/xmlspace.xsd"; | |
43 | + | |
44 | + private static final URI EMPTY_URI = URI.create(""); | |
45 | + | |
46 | + private static final Class<?> THISCLASS = XmlResourceResolver.class; | |
47 | + | |
48 | + | |
49 | + private final Map<URI, URI> uriMap; | |
50 | + | |
51 | + | |
52 | + /** | |
53 | + * コンストラクタ。 | |
54 | + */ | |
55 | + public XmlResourceResolver(){ | |
56 | + super(); | |
57 | + | |
58 | + assert this.getClass().equals(THISCLASS); | |
59 | + | |
60 | + Map<URI, URI> map; | |
61 | + map = new HashMap<URI, URI>(); | |
62 | + map = Collections.synchronizedMap(map); | |
63 | + this.uriMap = map; | |
64 | + | |
65 | + URL redirectRes = THISCLASS.getResource(LOCAL_SCHEMA_XML); | |
66 | + String redirectResName = redirectRes.toString(); | |
67 | + | |
68 | + URI originalURI = URI.create(SCHEMA_XML); | |
69 | + URI redirectURI = URI.create(redirectResName); | |
70 | + | |
71 | + putRedirectedImpl(originalURI, redirectURI); | |
72 | + | |
73 | + return; | |
74 | + } | |
75 | + | |
76 | + | |
77 | + /** | |
78 | + * 絶対URIと相対URIを合成したURIを返す。 | |
79 | + * 正規化も行われる。 | |
80 | + * @param base 絶対URIでなければならない。nullでもよい。 | |
81 | + * @param relative 絶対URIでもよいがその場合baseは無視される。null可。 | |
82 | + * @return 合成結果のURLオブジェクト。必ず絶対URIになる。 | |
83 | + * @throws java.net.URISyntaxException URIとして変。 | |
84 | + * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。 | |
85 | + */ | |
86 | + protected static URI buildBaseRelativeURI(String base, String relative) | |
87 | + throws URISyntaxException, | |
88 | + IllegalArgumentException { | |
89 | + URI baseURI; | |
90 | + if(base != null){ | |
91 | + baseURI = new URI(base); | |
92 | + if( ! baseURI.isAbsolute() ){ | |
93 | + throw new IllegalArgumentException(); | |
94 | + } | |
95 | + }else{ | |
96 | + baseURI = null; | |
97 | + } | |
98 | + | |
99 | + URI relativeURI; | |
100 | + if(relative != null){ | |
101 | + relativeURI = new URI(relative); | |
102 | + }else{ | |
103 | + relativeURI = EMPTY_URI; | |
104 | + } | |
105 | + | |
106 | + URI resultURI; | |
107 | + if(baseURI == null || relativeURI.isAbsolute()){ | |
108 | + resultURI = relativeURI; | |
109 | + }else{ | |
110 | + resultURI = baseURI.resolve(relativeURI); | |
111 | + } | |
112 | + | |
113 | + if( ! resultURI.isAbsolute() ){ | |
114 | + throw new IllegalArgumentException(); | |
115 | + } | |
116 | + | |
117 | + resultURI = resultURI.normalize(); | |
118 | + | |
119 | + return resultURI; | |
120 | + } | |
121 | + | |
122 | + /** | |
123 | + * LSInput実装を生成する。 | |
124 | + * @return LSInput実装 | |
125 | + */ | |
126 | + public static LSInput createLSInput(){ | |
127 | + LSInput input = new LSInputImpl(); | |
128 | + return input; | |
129 | + } | |
130 | + | |
131 | + | |
132 | + /** | |
133 | + * オリジナルURIとリダイレクト先のURIを登録する。 | |
134 | + * オリジナルURIへのアクセスはリダイレクトされる。 | |
135 | + * @param original オリジナルURI | |
136 | + * @param redirect リダイレクトURI | |
137 | + */ | |
138 | + private void putRedirectedImpl(URI original, URI redirect){ | |
139 | + URI oridinalNorm = original.normalize(); | |
140 | + URI redirectNorm = redirect.normalize(); | |
141 | + | |
142 | + this.uriMap.put(oridinalNorm, redirectNorm); | |
143 | + | |
144 | + return; | |
145 | + } | |
146 | + | |
147 | + /** | |
148 | + * オリジナルURIとリダイレクト先のURIを登録する。 | |
149 | + * オリジナルURIへのアクセスはリダイレクトされる。 | |
150 | + * @param original オリジナルURI | |
151 | + * @param redirect リダイレクトURI | |
152 | + */ | |
153 | + public void putRedirected(URI original, URI redirect){ | |
154 | + putRedirectedImpl(original, redirect); | |
155 | + return; | |
156 | + } | |
157 | + | |
158 | + /** | |
159 | + * ローカル版リソース参照解決を登録する。 | |
160 | + * @param lsc ローカル版リソース参照解決 | |
161 | + */ | |
162 | + public void putRedirected(LocalXmlResource lsc){ | |
163 | + URI original = lsc.getOriginalResource(); | |
164 | + if(original == null) return; | |
165 | + | |
166 | + URI local = lsc.getLocalResource(); | |
167 | + | |
168 | + putRedirected(original, local); | |
169 | + | |
170 | + return; | |
171 | + } | |
172 | + | |
173 | + /** | |
174 | + * 別リゾルバの登録内容を追加登録する。 | |
175 | + * @param other 別リゾルバ | |
176 | + */ | |
177 | + public void putRedirected(XmlResourceResolver other){ | |
178 | + this.uriMap.putAll(other.uriMap); | |
179 | + return; | |
180 | + } | |
181 | + | |
182 | + /** | |
183 | + * 登録済みリダイレクト先URIを返す。 | |
184 | + * @param original オリジナルURI | |
185 | + * @return リダイレクト先URI。未登録の場合はnull | |
186 | + */ | |
187 | + public URI getRedirected(URI original){ | |
188 | + URI keyURI = original.normalize(); | |
189 | + URI resourceURI = this.uriMap.get(keyURI); | |
190 | + return resourceURI; | |
191 | + } | |
192 | + | |
193 | + /** | |
194 | + * 登録済みリダイレクト先URIを返す。 | |
195 | + * @param original オリジナルURI | |
196 | + * @return リダイレクト先URI。未登録の場合はオリジナルを返す | |
197 | + */ | |
198 | + public URI resolveRedirected(URI original){ | |
199 | + URI result = getRedirected(original); | |
200 | + if(result == null) result = original; | |
201 | + return result; | |
202 | + } | |
203 | + | |
204 | + /** | |
205 | + * 登録済みリダイレクト先リソースの入力ストリームを得る。 | |
206 | + * @param originalURI オリジナルURI | |
207 | + * @return 入力ストリーム。リダイレクト先が未登録の場合はnull | |
208 | + * @throws java.io.IOException 入出力エラー。 | |
209 | + * もしくはリソースが見つからない。 | |
210 | + */ | |
211 | + private InputStream getXMLResourceAsStream(URI originalURI) | |
212 | + throws IOException{ | |
213 | + URI resourceURI = getRedirected(originalURI); | |
214 | + if(resourceURI == null) return null; | |
215 | + | |
216 | + URL resourceURL = resourceURI.toURL(); | |
217 | + InputStream is = resourceURL.openStream(); | |
218 | + | |
219 | + return is; | |
220 | + } | |
221 | + | |
222 | + /** | |
223 | + * {@inheritDoc} | |
224 | + * URL変換したあとの入力ソースを返す。 | |
225 | + * @param type {@inheritDoc} | |
226 | + * @param namespaceURI {@inheritDoc} | |
227 | + * @param publicId {@inheritDoc} | |
228 | + * @param systemId {@inheritDoc} | |
229 | + * @param baseURI {@inheritDoc} | |
230 | + * @return {@inheritDoc} | |
231 | + */ | |
232 | + @Override | |
233 | + public LSInput resolveResource(String type, | |
234 | + String namespaceURI, | |
235 | + String publicId, | |
236 | + String systemId, | |
237 | + String baseURI ){ | |
238 | + if(systemId == null) return null; | |
239 | + | |
240 | + URI originalURI; | |
241 | + try{ | |
242 | + originalURI = buildBaseRelativeURI(baseURI, systemId); | |
243 | + }catch(URISyntaxException e){ | |
244 | + return null; | |
245 | + } | |
246 | + | |
247 | + InputStream is; | |
248 | + try{ | |
249 | + is = getXMLResourceAsStream(originalURI); | |
250 | + }catch(IOException e){ | |
251 | + return null; | |
252 | + } | |
253 | + if(is == null) return null; | |
254 | + | |
255 | + LSInput input = createLSInput(); | |
256 | + input.setBaseURI(baseURI); | |
257 | + input.setPublicId(publicId); | |
258 | + input.setSystemId(systemId); | |
259 | + input.setByteStream(is); | |
260 | + | |
261 | + return input; | |
262 | + } | |
263 | + | |
264 | + /** | |
265 | + * {@inheritDoc} | |
266 | + * URL変換したあとの入力ソースを返す。 | |
267 | + * @param publicId {@inheritDoc} | |
268 | + * @param systemId {@inheritDoc} | |
269 | + * @return {@inheritDoc} | |
270 | + * @throws org.xml.sax.SAXException {@inheritDoc} | |
271 | + * @throws java.io.IOException {@inheritDoc} | |
272 | + */ | |
273 | + @Override | |
274 | + public InputSource resolveEntity(String publicId, String systemId) | |
275 | + throws SAXException, IOException{ | |
276 | + if(systemId == null) return null; | |
277 | + | |
278 | + URI originalUri; | |
279 | + try{ | |
280 | + originalUri = new URI(systemId); | |
281 | + }catch(URISyntaxException e){ | |
282 | + return null; | |
283 | + } | |
284 | + | |
285 | + InputStream is = getXMLResourceAsStream(originalUri); | |
286 | + if(is == null) return null; | |
287 | + | |
288 | + InputSource source = new InputSource(is); | |
289 | + source.setPublicId(publicId); | |
290 | + source.setSystemId(systemId); | |
291 | + | |
292 | + return source; | |
293 | + } | |
294 | + | |
295 | + /** | |
296 | + * JRE1.5用LSInput実装。 | |
297 | + * JRE1.6なら | |
298 | + * org.w3c.dom.ls.DOMImplementationLS#createLSInput() | |
299 | + * で生成可能かも。 | |
300 | + */ | |
301 | + private static final class LSInputImpl implements LSInput { | |
302 | + | |
303 | + private String baseURI = null; | |
304 | + private InputStream byteStream = null; | |
305 | + private boolean certifiedText = false; | |
306 | + private Reader characterStream = null; | |
307 | + private String encoding = null; | |
308 | + private String publicId = null; | |
309 | + private String stringData = null; | |
310 | + private String systemId = null; | |
311 | + | |
312 | + /** | |
313 | + * コンストラクタ。 | |
314 | + */ | |
315 | + LSInputImpl(){ | |
316 | + super(); | |
317 | + return; | |
318 | + } | |
319 | + | |
320 | + /** | |
321 | + * {@inheritDoc} | |
322 | + * @return {@inheritDoc} | |
323 | + */ | |
324 | + @Override | |
325 | + public String getBaseURI(){ | |
326 | + return this.baseURI; | |
327 | + } | |
328 | + | |
329 | + /** | |
330 | + * {@inheritDoc} | |
331 | + * @param baseURI {@inheritDoc} | |
332 | + */ | |
333 | + @Override | |
334 | + public void setBaseURI(String baseURI){ | |
335 | + this.baseURI = baseURI; | |
336 | + return; | |
337 | + } | |
338 | + | |
339 | + /** | |
340 | + * {@inheritDoc} | |
341 | + * @return {@inheritDoc} | |
342 | + */ | |
343 | + @Override | |
344 | + public InputStream getByteStream(){ | |
345 | + return this.byteStream; | |
346 | + } | |
347 | + | |
348 | + /** | |
349 | + * {@inheritDoc} | |
350 | + * @param byteStream {@inheritDoc} | |
351 | + */ | |
352 | + @Override | |
353 | + public void setByteStream(InputStream byteStream){ | |
354 | + this.byteStream = byteStream; | |
355 | + } | |
356 | + | |
357 | + /** | |
358 | + * {@inheritDoc} | |
359 | + * @return {@inheritDoc} | |
360 | + */ | |
361 | + @Override | |
362 | + public boolean getCertifiedText(){ | |
363 | + return this.certifiedText; | |
364 | + } | |
365 | + | |
366 | + /** | |
367 | + * {@inheritDoc} | |
368 | + * @param certifiedText {@inheritDoc} | |
369 | + */ | |
370 | + @Override | |
371 | + public void setCertifiedText(boolean certifiedText){ | |
372 | + this.certifiedText = certifiedText; | |
373 | + return; | |
374 | + } | |
375 | + | |
376 | + /** | |
377 | + * {@inheritDoc} | |
378 | + * @return {@inheritDoc} | |
379 | + */ | |
380 | + @Override | |
381 | + public Reader getCharacterStream(){ | |
382 | + return this.characterStream; | |
383 | + } | |
384 | + | |
385 | + /** | |
386 | + * {@inheritDoc} | |
387 | + * @param characterStream {@inheritDoc} | |
388 | + */ | |
389 | + @Override | |
390 | + public void setCharacterStream(Reader characterStream){ | |
391 | + this.characterStream = characterStream; | |
392 | + } | |
393 | + | |
394 | + /** | |
395 | + * {@inheritDoc} | |
396 | + * @return {@inheritDoc} | |
397 | + */ | |
398 | + @Override | |
399 | + public String getEncoding(){ | |
400 | + return this.encoding; | |
401 | + } | |
402 | + | |
403 | + /** | |
404 | + * {@inheritDoc} | |
405 | + * @param encoding {@inheritDoc} | |
406 | + */ | |
407 | + @Override | |
408 | + public void setEncoding(String encoding){ | |
409 | + this.encoding = encoding; | |
410 | + return; | |
411 | + } | |
412 | + | |
413 | + /** | |
414 | + * {@inheritDoc} | |
415 | + * @return {@inheritDoc} | |
416 | + */ | |
417 | + @Override | |
418 | + public String getPublicId(){ | |
419 | + return this.publicId; | |
420 | + } | |
421 | + | |
422 | + /** | |
423 | + * {@inheritDoc} | |
424 | + * @param publicId {@inheritDoc} | |
425 | + */ | |
426 | + @Override | |
427 | + public void setPublicId(String publicId){ | |
428 | + this.publicId = publicId; | |
429 | + return; | |
430 | + } | |
431 | + | |
432 | + /** | |
433 | + * {@inheritDoc} | |
434 | + * @return {@inheritDoc} | |
435 | + */ | |
436 | + @Override | |
437 | + public String getStringData(){ | |
438 | + return this.stringData; | |
439 | + } | |
440 | + | |
441 | + /** | |
442 | + * {@inheritDoc} | |
443 | + * @param stringData {@inheritDoc} | |
444 | + */ | |
445 | + @Override | |
446 | + public void setStringData(String stringData){ | |
447 | + this.stringData = stringData; | |
448 | + return; | |
449 | + } | |
450 | + | |
451 | + /** | |
452 | + * {@inheritDoc} | |
453 | + * @return {@inheritDoc} | |
454 | + */ | |
455 | + @Override | |
456 | + public String getSystemId(){ | |
457 | + return this.systemId; | |
458 | + } | |
459 | + | |
460 | + /** | |
461 | + * {@inheritDoc} | |
462 | + * @param systemId {@inheritDoc} | |
463 | + */ | |
464 | + @Override | |
465 | + public void setSystemId(String systemId){ | |
466 | + this.systemId = systemId; | |
467 | + return; | |
468 | + } | |
469 | + | |
470 | + } | |
471 | + | |
472 | +} |
@@ -0,0 +1,14 @@ | ||
1 | +/* | |
2 | + * package information for Javadoc | |
3 | + * | |
4 | + * License : The MIT License | |
5 | + * Copyright(c) 2010 MikuToga Partners | |
6 | + */ | |
7 | + | |
8 | +/** | |
9 | + * MikuToga XML共通ライブラリ。 | |
10 | + */ | |
11 | + | |
12 | +package jp.sfjp.mikutoga.xml; | |
13 | + | |
14 | +/* EOF */ |
@@ -1,699 +0,0 @@ | ||
1 | -/* | |
2 | - * abstract xml exporter | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2013 MikuToga Partners | |
6 | - */ | |
7 | - | |
8 | -package jp.sourceforge.mikutoga.xml; | |
9 | - | |
10 | -import java.io.IOException; | |
11 | -import java.util.regex.Matcher; | |
12 | -import java.util.regex.Pattern; | |
13 | -import javax.xml.bind.DatatypeConverter; | |
14 | - | |
15 | -/** | |
16 | - * Appendable実装に依存したXMLエクスポータの半実装。 | |
17 | - * UCS4は未サポート。 | |
18 | - */ | |
19 | -abstract class AbstractXmlExporter implements XmlExporter{ | |
20 | - | |
21 | - /** デフォルトの改行文字列。 */ | |
22 | - private static final String DEF_NL = "\n"; // 0x0a(LF) | |
23 | - /** デフォルトのインデント単位。 */ | |
24 | - private static final String DEF_INDENT_UNIT = "\u0020\u0020"; // ␣␣ | |
25 | - | |
26 | - private static final char CH_SP = '\u0020'; // ␣ | |
27 | - private static final char CH_YEN = '\u00a5'; // ¥ | |
28 | - private static final char CH_BSLASH = (char)0x005c; // \ | |
29 | - private static final char CH_DQ = '\u0022'; // " | |
30 | - private static final char CH_SQ = (char)0x0027; // ' | |
31 | - private static final char CH_EQ = '='; // = | |
32 | - private static final char CH_LT = '<'; | |
33 | - private static final char CH_GT = '>'; | |
34 | - | |
35 | - private static final String COMM_START = "<!--"; | |
36 | - private static final String COMM_END = "-->"; | |
37 | - | |
38 | - private static final Pattern NUM_FUZZY = | |
39 | - Pattern.compile("([^.]*\\.[0-9][0-9]*?)0+"); | |
40 | - | |
41 | - private static final String REF_HEX = "&#x"; | |
42 | - private static final int HEX_EXP = 4; // 2 ** 4 == 16 | |
43 | - private static final int MASK_1HEX = (1 << HEX_EXP) - 1; // 0b00001111 | |
44 | - private static final int MAX_OCTET = (1 << Byte.SIZE) - 1; // 0xff | |
45 | - private static final char[] HEXCHAR_TABLE = { | |
46 | - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', | |
47 | - 'A', 'B', 'C', 'D', 'E', 'F', | |
48 | - }; | |
49 | - | |
50 | - static{ | |
51 | - assert HEX_EXP * 2 == Byte.SIZE; | |
52 | - assert HEXCHAR_TABLE.length == (1 << HEX_EXP); | |
53 | - } | |
54 | - | |
55 | - | |
56 | - private boolean basicLatinOnlyOut = true; | |
57 | - private String newline = DEF_NL; | |
58 | - private String indentUnit = DEF_INDENT_UNIT; | |
59 | - private int indentNest = 0; | |
60 | - | |
61 | - | |
62 | - /** | |
63 | - * コンストラクタ。 | |
64 | - */ | |
65 | - protected AbstractXmlExporter(){ | |
66 | - super(); | |
67 | - return; | |
68 | - } | |
69 | - | |
70 | - | |
71 | - /** | |
72 | - * ASCIIコード相当(UCS:Basic-Latin)の文字か否か判定する。 | |
73 | - * <p>※ Basic-Latinには各種制御文字も含まれる。 | |
74 | - * @param ch 判定対象文字 | |
75 | - * @return Basic-Latin文字ならtrue | |
76 | - * <a href="http://www.unicode.org/charts/PDF/U0000.pdf"> | |
77 | - * Unicode 6.2 Controls and Basic Latin | |
78 | - * </a> | |
79 | - */ | |
80 | - protected static boolean isBasicLatin(char ch){ | |
81 | - if('\u0000' <= ch && ch <= '\u007f'){ | |
82 | - return true; | |
83 | - } | |
84 | - return false; | |
85 | - } | |
86 | - | |
87 | - /** | |
88 | - * 冗長な実数出力を抑止する。 | |
89 | - * <p>DatatypeConverterにおけるJDK1.6系と1.7系の仕様変更を吸収する。 | |
90 | - * <p>0.001fは"0.0010"ではなく"0.001"と出力される。 | |
91 | - * <p>指数表記での冗長桁は無視する。 | |
92 | - * @param numTxt 実数表記 | |
93 | - * @return 冗長桁が抑止された実数表記 | |
94 | - * @see javax.xml.bind.DatatypeConverter | |
95 | - */ | |
96 | - protected static String chopFuzzyZero(String numTxt){ | |
97 | - String result; | |
98 | - | |
99 | - Matcher matcher = NUM_FUZZY.matcher(numTxt); | |
100 | - if(matcher.matches()){ | |
101 | - result = matcher.group(1); | |
102 | - }else{ | |
103 | - result = numTxt; | |
104 | - } | |
105 | - | |
106 | - return result; | |
107 | - } | |
108 | - | |
109 | - | |
110 | - /** | |
111 | - * {@inheritDoc} | |
112 | - * @param ch {@inheritDoc} | |
113 | - * @return {@inheritDoc} | |
114 | - * @throws IOException {@inheritDoc} | |
115 | - */ | |
116 | - @Override | |
117 | - public abstract Appendable append(char ch) throws IOException; | |
118 | - | |
119 | - /** | |
120 | - * {@inheritDoc} | |
121 | - * @param seq {@inheritDoc} | |
122 | - * @return {@inheritDoc} | |
123 | - * @throws IOException {@inheritDoc} | |
124 | - */ | |
125 | - @Override | |
126 | - public abstract Appendable append(CharSequence seq) throws IOException; | |
127 | - | |
128 | - /** | |
129 | - * {@inheritDoc} | |
130 | - * @param seq {@inheritDoc} | |
131 | - * @param start {@inheritDoc} | |
132 | - * @param end {@inheritDoc} | |
133 | - * @return {@inheritDoc} | |
134 | - * @throws IOException {@inheritDoc} | |
135 | - */ | |
136 | - @Override | |
137 | - public abstract Appendable append(CharSequence seq, int start, int end) | |
138 | - throws IOException; | |
139 | - | |
140 | - /** | |
141 | - * {@inheritDoc} | |
142 | - * @throws IOException {@inheritDoc} | |
143 | - */ | |
144 | - @Override | |
145 | - public abstract void flush() throws IOException; | |
146 | - | |
147 | - /** | |
148 | - * {@inheritDoc} | |
149 | - * @throws IOException {@inheritDoc} | |
150 | - */ | |
151 | - @Override | |
152 | - public abstract void close() throws IOException; | |
153 | - | |
154 | - | |
155 | - /** | |
156 | - * {@inheritDoc} | |
157 | - * @param ch {@inheritDoc} | |
158 | - * @return {@inheritDoc} | |
159 | - * @throws IOException {@inheritDoc} | |
160 | - */ | |
161 | - @Override | |
162 | - public XmlExporter putRawCh(char ch) throws IOException{ | |
163 | - append(ch); | |
164 | - return this; | |
165 | - } | |
166 | - | |
167 | - /** | |
168 | - * {@inheritDoc} | |
169 | - * @param seq {@inheritDoc} | |
170 | - * @return {@inheritDoc} | |
171 | - * @throws IOException {@inheritDoc} | |
172 | - */ | |
173 | - @Override | |
174 | - public XmlExporter putRawText(CharSequence seq) | |
175 | - throws IOException{ | |
176 | - append(seq); | |
177 | - return this; | |
178 | - } | |
179 | - | |
180 | - /** | |
181 | - * {@inheritDoc} | |
182 | - * @return {@inheritDoc} | |
183 | - * @throws IOException {@inheritDoc} | |
184 | - */ | |
185 | - @Override | |
186 | - public XmlExporter sp() throws IOException{ | |
187 | - putRawCh(CH_SP); | |
188 | - return this; | |
189 | - } | |
190 | - | |
191 | - /** | |
192 | - * {@inheritDoc} | |
193 | - * @param count {@inheritDoc} | |
194 | - * @return {@inheritDoc} | |
195 | - * @throws IOException {@inheritDoc} | |
196 | - */ | |
197 | - @Override | |
198 | - public XmlExporter sp(int count) throws IOException{ | |
199 | - for(int ct = 1; ct <= count; ct++){ | |
200 | - sp(); | |
201 | - } | |
202 | - return this; | |
203 | - } | |
204 | - | |
205 | - /** | |
206 | - * {@inheritDoc} | |
207 | - * @return {@inheritDoc} | |
208 | - */ | |
209 | - @Override | |
210 | - public String getNewLine(){ | |
211 | - return this.newline; | |
212 | - } | |
213 | - | |
214 | - /** | |
215 | - * {@inheritDoc} | |
216 | - * @param newLine {@inheritDoc} | |
217 | - * @throws NullPointerException {@inheritDoc} | |
218 | - */ | |
219 | - @Override | |
220 | - public void setNewLine(String newLine) throws NullPointerException{ | |
221 | - if(newLine == null) throw new NullPointerException(); | |
222 | - this.newline = newLine; | |
223 | - return; | |
224 | - } | |
225 | - | |
226 | - /** | |
227 | - * {@inheritDoc} | |
228 | - * @return {@inheritDoc} | |
229 | - * @throws IOException {@inheritDoc} | |
230 | - */ | |
231 | - @Override | |
232 | - public XmlExporter ln() throws IOException{ | |
233 | - putRawText(getNewLine()); | |
234 | - return this; | |
235 | - } | |
236 | - | |
237 | - /** | |
238 | - * {@inheritDoc} | |
239 | - * @param count {@inheritDoc} | |
240 | - * @return {@inheritDoc} | |
241 | - * @throws IOException {@inheritDoc} | |
242 | - */ | |
243 | - @Override | |
244 | - public XmlExporter ln(int count) throws IOException{ | |
245 | - for(int ct = 1; ct <= count; ct++){ | |
246 | - ln(); | |
247 | - } | |
248 | - return this; | |
249 | - } | |
250 | - | |
251 | - /** | |
252 | - * {@inheritDoc} | |
253 | - * @return {@inheritDoc} | |
254 | - */ | |
255 | - @Override | |
256 | - public String getIndentUnit(){ | |
257 | - return this.indentUnit; | |
258 | - } | |
259 | - | |
260 | - /** | |
261 | - * {@inheritDoc} | |
262 | - * @param indUnit {@inheritDoc} | |
263 | - * @throws NullPointerException {@inheritDoc} | |
264 | - */ | |
265 | - @Override | |
266 | - public void setIndentUnit(String indUnit) throws NullPointerException{ | |
267 | - if(indUnit == null) throw new NullPointerException(); | |
268 | - this.indentUnit = indUnit; | |
269 | - return; | |
270 | - } | |
271 | - | |
272 | - /** | |
273 | - * {@inheritDoc} | |
274 | - */ | |
275 | - @Override | |
276 | - public void pushNest(){ | |
277 | - this.indentNest++; | |
278 | - return; | |
279 | - } | |
280 | - | |
281 | - /** | |
282 | - * {@inheritDoc} | |
283 | - */ | |
284 | - @Override | |
285 | - public void popNest(){ | |
286 | - this.indentNest--; | |
287 | - if(this.indentNest < 0) this.indentNest = 0; | |
288 | - return; | |
289 | - } | |
290 | - | |
291 | - /** | |
292 | - * {@inheritDoc} | |
293 | - * @return {@inheritDoc} | |
294 | - */ | |
295 | - @Override | |
296 | - public int getIndentLevel(){ | |
297 | - return this.indentNest; | |
298 | - } | |
299 | - | |
300 | - /** | |
301 | - * {@inheritDoc} | |
302 | - * @return {@inheritDoc} | |
303 | - * @throws IOException {@inheritDoc} | |
304 | - */ | |
305 | - @Override | |
306 | - public XmlExporter ind() throws IOException{ | |
307 | - int level = getIndentLevel(); | |
308 | - for(int ct = 1; ct <= level; ct++){ | |
309 | - putRawText(getIndentUnit()); | |
310 | - } | |
311 | - return this; | |
312 | - } | |
313 | - | |
314 | - /** | |
315 | - * {@inheritDoc} | |
316 | - * @return {@inheritDoc} | |
317 | - */ | |
318 | - @Override | |
319 | - public boolean isBasicLatinOnlyOut(){ | |
320 | - return this.basicLatinOnlyOut; | |
321 | - } | |
322 | - | |
323 | - /** | |
324 | - * {@inheritDoc} | |
325 | - * @param bool {@inheritDoc} | |
326 | - */ | |
327 | - @Override | |
328 | - public void setBasicLatinOnlyOut(boolean bool){ | |
329 | - this.basicLatinOnlyOut = bool; | |
330 | - return; | |
331 | - } | |
332 | - | |
333 | - /** | |
334 | - * {@inheritDoc} | |
335 | - * @param ch {@inheritDoc} | |
336 | - * @return {@inheritDoc} | |
337 | - * @throws IOException {@inheritDoc} | |
338 | - */ | |
339 | - @Override | |
340 | - public XmlExporter putCharRef2Hex(char ch) throws IOException{ | |
341 | - if(ch > MAX_OCTET) return putCharRef4Hex(ch); | |
342 | - | |
343 | - int ibits = ch; // 常に正なので符号拡張なし | |
344 | - | |
345 | - int idx4 = ibits & MASK_1HEX; | |
346 | - ibits >>= HEX_EXP; | |
347 | - int idx3 = ibits & MASK_1HEX; | |
348 | - | |
349 | - char hex3 = HEXCHAR_TABLE[idx3]; | |
350 | - char hex4 = HEXCHAR_TABLE[idx4]; | |
351 | - | |
352 | - putRawText(REF_HEX).putRawCh(hex3).putRawCh(hex4) | |
353 | - .putRawCh(';'); | |
354 | - | |
355 | - return this; | |
356 | - } | |
357 | - | |
358 | - /** | |
359 | - * {@inheritDoc} | |
360 | - * @param ch {@inheritDoc} | |
361 | - * @return {@inheritDoc} | |
362 | - * @throws IOException {@inheritDoc} | |
363 | - */ | |
364 | - @Override | |
365 | - public XmlExporter putCharRef4Hex(char ch) throws IOException{ | |
366 | - int ibits = ch; // 常に正なので符号拡張なし | |
367 | - | |
368 | - int idx4 = ibits & MASK_1HEX; | |
369 | - ibits >>= HEX_EXP; | |
370 | - int idx3 = ibits & MASK_1HEX; | |
371 | - ibits >>= HEX_EXP; | |
372 | - int idx2 = ibits & MASK_1HEX; | |
373 | - ibits >>= HEX_EXP; | |
374 | - int idx1 = ibits & MASK_1HEX; | |
375 | - | |
376 | - char hex1 = HEXCHAR_TABLE[idx1]; | |
377 | - char hex2 = HEXCHAR_TABLE[idx2]; | |
378 | - char hex3 = HEXCHAR_TABLE[idx3]; | |
379 | - char hex4 = HEXCHAR_TABLE[idx4]; | |
380 | - | |
381 | - putRawText(REF_HEX).putRawCh(hex1).putRawCh(hex2) | |
382 | - .putRawCh(hex3).putRawCh(hex4) | |
383 | - .putRawCh(';'); | |
384 | - | |
385 | - return this; | |
386 | - } | |
387 | - | |
388 | - /** | |
389 | - * {@inheritDoc} | |
390 | - * @param ch {@inheritDoc} | |
391 | - * @return {@inheritDoc} | |
392 | - * @throws IOException {@inheritDoc} | |
393 | - */ | |
394 | - @Override | |
395 | - public XmlExporter putCh(char ch) throws IOException{ | |
396 | - if(Character.isISOControl(ch)){ | |
397 | - putCharRef2Hex(ch); | |
398 | - return this; | |
399 | - } | |
400 | - | |
401 | - String escTxt; | |
402 | - switch(ch){ | |
403 | - case '&': escTxt = "&"; break; | |
404 | - case CH_LT: escTxt = "<"; break; | |
405 | - case CH_GT: escTxt = ">"; break; | |
406 | - case CH_DQ: escTxt = """; break; | |
407 | - case CH_SQ: escTxt = "'"; break; | |
408 | - default: escTxt = null; break; | |
409 | - } | |
410 | - | |
411 | - if(escTxt != null){ | |
412 | - putRawText(escTxt); | |
413 | - }else{ | |
414 | - putRawCh(ch); | |
415 | - } | |
416 | - | |
417 | - return this; | |
418 | - } | |
419 | - | |
420 | - /** | |
421 | - * {@inheritDoc} | |
422 | - * @param content {@inheritDoc} | |
423 | - * @return {@inheritDoc} | |
424 | - * @throws IOException {@inheritDoc} | |
425 | - */ | |
426 | - @Override | |
427 | - public XmlExporter putContent(CharSequence content) | |
428 | - throws IOException{ | |
429 | - int length = content.length(); | |
430 | - | |
431 | - char prev = '\0'; | |
432 | - for(int pos = 0; pos < length; pos++){ | |
433 | - char ch = content.charAt(pos); | |
434 | - | |
435 | - if( isBasicLatinOnlyOut() && ! isBasicLatin(ch) ){ | |
436 | - putCharRef4Hex(ch); | |
437 | - }else if(ch == CH_YEN){ | |
438 | - putRawCh(CH_BSLASH); | |
439 | - }else if(Character.isSpaceChar(ch)){ | |
440 | - if(ch == CH_SP && prev != CH_SP){ | |
441 | - putRawCh(ch); | |
442 | - }else{ | |
443 | - putCharRef2Hex(ch); | |
444 | - } | |
445 | - }else{ | |
446 | - putCh(ch); | |
447 | - } | |
448 | - | |
449 | - prev = ch; | |
450 | - } | |
451 | - | |
452 | - return this; | |
453 | - } | |
454 | - | |
455 | - /** | |
456 | - * {@inheritDoc} | |
457 | - * @param comment {@inheritDoc} | |
458 | - * @return {@inheritDoc} | |
459 | - * @throws IOException {@inheritDoc} | |
460 | - */ | |
461 | - @Override | |
462 | - public XmlExporter putCommentContent(CharSequence comment) | |
463 | - throws IOException{ | |
464 | - int length = comment.length(); | |
465 | - | |
466 | - char prev = '\0'; | |
467 | - for(int pos = 0; pos < length; pos++){ | |
468 | - char ch = comment.charAt(pos); | |
469 | - | |
470 | - if(ch == '\n'){ | |
471 | - ln(); | |
472 | - }else if('\u0000' <= ch && ch <= '\u001f'){ | |
473 | - putRawCh((char)('\u2400' + ch)); | |
474 | - }else if(ch == '\u007f'){ | |
475 | - putRawCh('\u2421'); | |
476 | - }else if(prev == '-' && ch == '-'){ | |
477 | - sp().putRawCh(ch); | |
478 | - }else{ | |
479 | - putRawCh(ch); | |
480 | - } | |
481 | - | |
482 | - prev = ch; | |
483 | - } | |
484 | - | |
485 | - return this; | |
486 | - } | |
487 | - | |
488 | - /** | |
489 | - * {@inheritDoc} | |
490 | - * @param comment {@inheritDoc} | |
491 | - * @return {@inheritDoc} | |
492 | - * @throws IOException {@inheritDoc} | |
493 | - */ | |
494 | - @Override | |
495 | - public XmlExporter putLineComment(CharSequence comment) | |
496 | - throws IOException{ | |
497 | - putRawText(COMM_START).sp(); | |
498 | - putCommentContent(comment); | |
499 | - sp().putRawText(COMM_END); | |
500 | - return this; | |
501 | - } | |
502 | - | |
503 | - /** | |
504 | - * {@inheritDoc} | |
505 | - * @param comment {@inheritDoc} | |
506 | - * @return {@inheritDoc} | |
507 | - * @throws IOException {@inheritDoc} | |
508 | - */ | |
509 | - @Override | |
510 | - public XmlExporter putBlockComment(CharSequence comment) | |
511 | - throws IOException{ | |
512 | - putRawText(COMM_START).ln(); | |
513 | - | |
514 | - putCommentContent(comment); | |
515 | - | |
516 | - int commentLength = comment.length(); | |
517 | - if(commentLength > 0){ | |
518 | - char lastCh = comment.charAt(commentLength - 1); | |
519 | - if(lastCh != '\n'){ | |
520 | - ln(); | |
521 | - } | |
522 | - } | |
523 | - | |
524 | - putRawText(COMM_END).ln(); | |
525 | - | |
526 | - return this; | |
527 | - } | |
528 | - | |
529 | - /** | |
530 | - * {@inheritDoc} | |
531 | - * @param tagName {@inheritDoc} | |
532 | - * @return {@inheritDoc} | |
533 | - * @throws IOException {@inheritDoc} | |
534 | - */ | |
535 | - @Override | |
536 | - public XmlExporter putOpenSTag(CharSequence tagName) | |
537 | - throws IOException{ | |
538 | - putRawCh(CH_LT); | |
539 | - putRawText(tagName); | |
540 | - return this; | |
541 | - } | |
542 | - | |
543 | - /** | |
544 | - * {@inheritDoc} | |
545 | - * @return {@inheritDoc} | |
546 | - * @throws IOException {@inheritDoc} | |
547 | - */ | |
548 | - @Override | |
549 | - public XmlExporter putCloseSTag() | |
550 | - throws IOException{ | |
551 | - putRawCh(CH_GT); | |
552 | - return this; | |
553 | - } | |
554 | - | |
555 | - /** | |
556 | - * {@inheritDoc} | |
557 | - * @param tagName {@inheritDoc} | |
558 | - * @return {@inheritDoc} | |
559 | - * @throws IOException {@inheritDoc} | |
560 | - */ | |
561 | - @Override | |
562 | - public XmlExporter putSimpleSTag(CharSequence tagName) | |
563 | - throws IOException{ | |
564 | - putRawCh(CH_LT); | |
565 | - putRawText(tagName); | |
566 | - putRawCh(CH_GT); | |
567 | - return this; | |
568 | - } | |
569 | - | |
570 | - /** | |
571 | - * {@inheritDoc} | |
572 | - * @param tagName {@inheritDoc} | |
573 | - * @return {@inheritDoc} | |
574 | - * @throws IOException {@inheritDoc} | |
575 | - */ | |
576 | - @Override | |
577 | - public XmlExporter putETag(CharSequence tagName) | |
578 | - throws IOException{ | |
579 | - putRawText("</"); | |
580 | - putRawText(tagName); | |
581 | - putRawCh(CH_GT); | |
582 | - return this; | |
583 | - } | |
584 | - | |
585 | - /** | |
586 | - * {@inheritDoc} | |
587 | - * @param tagName {@inheritDoc} | |
588 | - * @return {@inheritDoc} | |
589 | - * @throws IOException {@inheritDoc} | |
590 | - */ | |
591 | - @Override | |
592 | - public XmlExporter putSimpleEmpty(CharSequence tagName) | |
593 | - throws IOException{ | |
594 | - putRawCh(CH_LT); | |
595 | - putRawText(tagName).sp(); | |
596 | - putCloseEmpty(); | |
597 | - return this; | |
598 | - } | |
599 | - | |
600 | - /** | |
601 | - * {@inheritDoc} | |
602 | - * @return {@inheritDoc} | |
603 | - * @throws IOException {@inheritDoc} | |
604 | - */ | |
605 | - @Override | |
606 | - public XmlExporter putCloseEmpty() | |
607 | - throws IOException{ | |
608 | - putRawText("/>"); | |
609 | - return this; | |
610 | - } | |
611 | - | |
612 | - /** | |
613 | - * {@inheritDoc} | |
614 | - * @param iVal {@inheritDoc} | |
615 | - * @return {@inheritDoc} | |
616 | - * @throws IOException {@inheritDoc} | |
617 | - */ | |
618 | - @Override | |
619 | - public XmlExporter putXsdInt(int iVal) throws IOException{ | |
620 | - String value = DatatypeConverter.printInt(iVal); | |
621 | - putRawText(value); | |
622 | - return this; | |
623 | - } | |
624 | - | |
625 | - /** | |
626 | - * {@inheritDoc} | |
627 | - * @param fVal {@inheritDoc} | |
628 | - * @return {@inheritDoc} | |
629 | - * @throws IOException {@inheritDoc} | |
630 | - */ | |
631 | - @Override | |
632 | - public XmlExporter putXsdFloat(float fVal) throws IOException{ | |
633 | - String value = DatatypeConverter.printFloat(fVal); | |
634 | - value = chopFuzzyZero(value); | |
635 | - putRawText(value); | |
636 | - return this; | |
637 | - } | |
638 | - | |
639 | - /** | |
640 | - * {@inheritDoc} | |
641 | - * @param attrName {@inheritDoc} | |
642 | - * @param iVal {@inheritDoc} | |
643 | - * @return {@inheritDoc} | |
644 | - * @throws IOException {@inheritDoc} | |
645 | - */ | |
646 | - @Override | |
647 | - public XmlExporter putIntAttr(CharSequence attrName, | |
648 | - int iVal) | |
649 | - throws IOException{ | |
650 | - putRawText(attrName).putRawCh(CH_EQ); | |
651 | - | |
652 | - putRawCh(CH_DQ); | |
653 | - putXsdInt(iVal); | |
654 | - putRawCh(CH_DQ); | |
655 | - | |
656 | - return this; | |
657 | - } | |
658 | - | |
659 | - /** | |
660 | - * {@inheritDoc} | |
661 | - * @param attrName {@inheritDoc} | |
662 | - * @param fVal {@inheritDoc} | |
663 | - * @return {@inheritDoc} | |
664 | - * @throws IOException {@inheritDoc} | |
665 | - */ | |
666 | - @Override | |
667 | - public XmlExporter putFloatAttr(CharSequence attrName, | |
668 | - float fVal) | |
669 | - throws IOException{ | |
670 | - putRawText(attrName).putRawCh(CH_EQ); | |
671 | - | |
672 | - putRawCh(CH_DQ); | |
673 | - putXsdFloat(fVal); | |
674 | - putRawCh(CH_DQ); | |
675 | - | |
676 | - return this; | |
677 | - } | |
678 | - | |
679 | - /** | |
680 | - * {@inheritDoc} | |
681 | - * @param attrName {@inheritDoc} | |
682 | - * @param content {@inheritDoc} | |
683 | - * @return {@inheritDoc} | |
684 | - * @throws IOException {@inheritDoc} | |
685 | - */ | |
686 | - @Override | |
687 | - public XmlExporter putAttr(CharSequence attrName, | |
688 | - CharSequence content) | |
689 | - throws IOException{ | |
690 | - putRawText(attrName).putRawCh(CH_EQ); | |
691 | - | |
692 | - putRawCh(CH_DQ); | |
693 | - putContent(content); | |
694 | - putRawCh(CH_DQ); | |
695 | - | |
696 | - return this; | |
697 | - } | |
698 | - | |
699 | -} |
@@ -1,106 +0,0 @@ | ||
1 | -/* | |
2 | - * basic xml exporter | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2010 MikuToga Partners | |
6 | - */ | |
7 | - | |
8 | -package jp.sourceforge.mikutoga.xml; | |
9 | - | |
10 | -import java.io.Closeable; | |
11 | -import java.io.Flushable; | |
12 | -import java.io.IOException; | |
13 | - | |
14 | -/** | |
15 | - * Appendable用XMLエクスポータ実装。 | |
16 | - */ | |
17 | -public class BasicXmlExporter extends AbstractXmlExporter{ | |
18 | - | |
19 | - private Appendable appendable = null; | |
20 | - | |
21 | - | |
22 | - /** | |
23 | - * コンストラクタ。 | |
24 | - */ | |
25 | - public BasicXmlExporter(){ | |
26 | - super(); | |
27 | - return; | |
28 | - } | |
29 | - | |
30 | - | |
31 | - /** | |
32 | - * 出力先アペンダを指定する。 | |
33 | - * @param app 出力先 | |
34 | - * @throws NullPointerException 引数がnull | |
35 | - */ | |
36 | - public void setAppendable(Appendable app) throws NullPointerException{ | |
37 | - if(app == null) throw new NullPointerException(); | |
38 | - | |
39 | - this.appendable = app; | |
40 | - | |
41 | - return; | |
42 | - } | |
43 | - | |
44 | - /** | |
45 | - * {@inheritDoc} | |
46 | - * @param ch {@inheritDoc} | |
47 | - * @return {@inheritDoc} | |
48 | - * @throws IOException {@inheritDoc} | |
49 | - */ | |
50 | - @Override | |
51 | - public Appendable append(char ch) throws IOException{ | |
52 | - return this.appendable.append(ch); | |
53 | - } | |
54 | - | |
55 | - /** | |
56 | - * {@inheritDoc} | |
57 | - * @param seq {@inheritDoc} | |
58 | - * @return {@inheritDoc} | |
59 | - * @throws IOException {@inheritDoc} | |
60 | - */ | |
61 | - @Override | |
62 | - public Appendable append(CharSequence seq) throws IOException{ | |
63 | - return this.appendable.append(seq); | |
64 | - } | |
65 | - | |
66 | - /** | |
67 | - * {@inheritDoc} | |
68 | - * @param seq {@inheritDoc} | |
69 | - * @param start {@inheritDoc} | |
70 | - * @param end {@inheritDoc} | |
71 | - * @return {@inheritDoc} | |
72 | - * @throws IOException {@inheritDoc} | |
73 | - */ | |
74 | - @Override | |
75 | - public Appendable append(CharSequence seq, int start, int end) | |
76 | - throws IOException{ | |
77 | - return this.appendable.append(seq, start, end); | |
78 | - } | |
79 | - | |
80 | - /** | |
81 | - * {@inheritDoc} | |
82 | - * 可能であれば出力をフラッシュする。 | |
83 | - * @throws IOException {@inheritDoc} | |
84 | - */ | |
85 | - @Override | |
86 | - public void flush() throws IOException{ | |
87 | - if(this.appendable instanceof Flushable){ | |
88 | - ((Flushable)this.appendable).flush(); | |
89 | - } | |
90 | - return; | |
91 | - } | |
92 | - | |
93 | - /** | |
94 | - * {@inheritDoc} | |
95 | - * 可能であれば出力をクローズする。 | |
96 | - * @throws IOException {@inheritDoc} | |
97 | - */ | |
98 | - @Override | |
99 | - public void close() throws IOException{ | |
100 | - if(this.appendable instanceof Closeable){ | |
101 | - ((Closeable)this.appendable).close(); | |
102 | - } | |
103 | - return; | |
104 | - } | |
105 | - | |
106 | -} |
@@ -1,63 +0,0 @@ | ||
1 | -/* | |
2 | - * XML custom error-handler | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2010 MikuToga Partners | |
6 | - */ | |
7 | - | |
8 | -package jp.sourceforge.mikutoga.xml; | |
9 | - | |
10 | -import org.xml.sax.ErrorHandler; | |
11 | -import org.xml.sax.SAXException; | |
12 | -import org.xml.sax.SAXParseException; | |
13 | - | |
14 | -/** | |
15 | - * 自製エラーハンドラ。 | |
16 | - * 例外を渡されれば即投げる。 | |
17 | - */ | |
18 | -public final class BotherHandler implements ErrorHandler{ | |
19 | - | |
20 | - /** | |
21 | - * 唯一のシングルトン。 | |
22 | - */ | |
23 | - public static final ErrorHandler HANDLER = new BotherHandler(); | |
24 | - | |
25 | - /** | |
26 | - * 隠しコンストラクタ。 | |
27 | - */ | |
28 | - private BotherHandler(){ | |
29 | - super(); | |
30 | - return; | |
31 | - } | |
32 | - | |
33 | - /** | |
34 | - * {@inheritDoc} | |
35 | - * @param exception {@inheritDoc} | |
36 | - * @throws SAXException {@inheritDoc} | |
37 | - */ | |
38 | - @Override | |
39 | - public void error(SAXParseException exception) throws SAXException{ | |
40 | - throw exception; | |
41 | - } | |
42 | - | |
43 | - /** | |
44 | - * {@inheritDoc} | |
45 | - * @param exception {@inheritDoc} | |
46 | - * @throws SAXException {@inheritDoc} | |
47 | - */ | |
48 | - @Override | |
49 | - public void fatalError(SAXParseException exception) throws SAXException{ | |
50 | - throw exception; | |
51 | - } | |
52 | - | |
53 | - /** | |
54 | - * {@inheritDoc} | |
55 | - * @param exception {@inheritDoc} | |
56 | - * @throws SAXException {@inheritDoc} | |
57 | - */ | |
58 | - @Override | |
59 | - public void warning(SAXParseException exception) throws SAXException{ | |
60 | - throw exception; | |
61 | - } | |
62 | - | |
63 | -} |
@@ -1,291 +0,0 @@ | ||
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 | -} |
@@ -1,363 +0,0 @@ | ||
1 | -/* | |
2 | - * XML DOM utilities | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2010 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 javax.xml.bind.DatatypeConverter; | |
15 | -import org.w3c.dom.Element; | |
16 | -import org.w3c.dom.Node; | |
17 | - | |
18 | -/** | |
19 | - * DOMユーティリティ。 | |
20 | - */ | |
21 | -public final class DomUtils { | |
22 | - | |
23 | - // 構文解析バグ回避。 | |
24 | - private static final char BS_CHAR = (char) 0x005c; | |
25 | - | |
26 | - /** | |
27 | - * 隠しコンストラクタ。 | |
28 | - */ | |
29 | - private DomUtils(){ | |
30 | - super(); | |
31 | - assert false; | |
32 | - throw new AssertionError(); | |
33 | - } | |
34 | - | |
35 | - /** | |
36 | - * 要素からxsd:string型属性値を読み取る。 | |
37 | - * @param elem 要素 | |
38 | - * @param attrName 属性名 | |
39 | - * @return 文字列 | |
40 | - * @throws TogaXmlException 属性値が見つからなかった。 | |
41 | - */ | |
42 | - public static String getStringAttr(Element elem, String attrName) | |
43 | - throws TogaXmlException{ | |
44 | - if( ! elem.hasAttribute(attrName) ){ | |
45 | - String message = "Attr:[" + attrName + "] " | |
46 | - + "was not found in " | |
47 | - + "Elem:[" + elem.getTagName()+"]"; | |
48 | - throw new TogaXmlException(message); | |
49 | - } | |
50 | - | |
51 | - String result; | |
52 | - try{ | |
53 | - result = elem.getAttribute(attrName); | |
54 | - }catch(IllegalArgumentException e){ | |
55 | - String message = "Invalid attribute form [" + attrName + "]"; | |
56 | - throw new TogaXmlException(message, e); | |
57 | - } | |
58 | - | |
59 | - return result; | |
60 | - } | |
61 | - | |
62 | - /** | |
63 | - * 要素からxsd:boolean型属性値を読み取る。 | |
64 | - * @param elem 要素 | |
65 | - * @param attrName 属性名 | |
66 | - * @return 真ならtrue | |
67 | - * @throws TogaXmlException 属性値が見つからなかった。 | |
68 | - */ | |
69 | - public static boolean getBooleanAttr(Element elem, String attrName) | |
70 | - throws TogaXmlException{ | |
71 | - String value = getStringAttr(elem, attrName); | |
72 | - | |
73 | - boolean result; | |
74 | - try{ | |
75 | - result = DatatypeConverter.parseBoolean(value); | |
76 | - }catch(IllegalArgumentException e){ | |
77 | - String message = | |
78 | - "Invalid boolean attribute form " | |
79 | - + "[" + attrName + "][" + value + "]"; | |
80 | - throw new TogaXmlException(message, e); | |
81 | - } | |
82 | - | |
83 | - return result; | |
84 | - } | |
85 | - | |
86 | - /** | |
87 | - * 要素からxsd:integer型属性値を読み取る。 | |
88 | - * @param elem 要素 | |
89 | - * @param attrName 属性名 | |
90 | - * @return int値 | |
91 | - * @throws TogaXmlException 属性値が見つからなかった。 | |
92 | - */ | |
93 | - public static int getIntegerAttr(Element elem, String attrName) | |
94 | - throws TogaXmlException{ | |
95 | - String value = getStringAttr(elem, attrName); | |
96 | - | |
97 | - int result; | |
98 | - try{ | |
99 | - result = DatatypeConverter.parseInt(value); | |
100 | - }catch(IllegalArgumentException e){ | |
101 | - String message = | |
102 | - "Invalid integer attribute form " | |
103 | - + "[" + attrName + "][" + value + "]"; | |
104 | - throw new TogaXmlException(message, e); | |
105 | - } | |
106 | - | |
107 | - return result; | |
108 | - } | |
109 | - | |
110 | - /** | |
111 | - * 要素からxsd:float型属性値を読み取る。 | |
112 | - * @param elem 要素 | |
113 | - * @param attrName 属性名 | |
114 | - * @return float値 | |
115 | - * @throws TogaXmlException 属性値が見つからなかった。 | |
116 | - */ | |
117 | - public static float getFloatAttr(Element elem, String attrName) | |
118 | - throws TogaXmlException{ | |
119 | - String value = getStringAttr(elem, attrName); | |
120 | - | |
121 | - float result; | |
122 | - try{ | |
123 | - result = DatatypeConverter.parseFloat(value); | |
124 | - }catch(IllegalArgumentException e){ | |
125 | - String message = | |
126 | - "Invalid float attribute form " | |
127 | - + "[" + attrName + "][" + value + "]"; | |
128 | - throw new TogaXmlException(message, e); | |
129 | - } | |
130 | - | |
131 | - return result; | |
132 | - } | |
133 | - | |
134 | - /** | |
135 | - * 要素から日本語Windows用ファイル名を属性値として読み取る。 | |
136 | - * 念のため文字U+00A5は文字U-005Cに変換される。 | |
137 | - * @param elem 要素 | |
138 | - * @param attrName 属性名 | |
139 | - * @return ファイル名 | |
140 | - * @throws TogaXmlException 属性値が見つからなかった。 | |
141 | - */ | |
142 | - public static String getSjisFileNameAttr(Element elem, String attrName) | |
143 | - throws TogaXmlException{ | |
144 | - String result; | |
145 | - try{ | |
146 | - result = getStringAttr(elem, attrName); | |
147 | - }catch(IllegalArgumentException e){ | |
148 | - String message = | |
149 | - "Invalid winfile attribute form " | |
150 | - + "[" + attrName + "]"; | |
151 | - throw new TogaXmlException(message, e); | |
152 | - } | |
153 | - | |
154 | - result = result.replace("" + '\u00a5', "" + BS_CHAR); | |
155 | - | |
156 | - return result; | |
157 | - } | |
158 | - | |
159 | - /** | |
160 | - * 指定された名前の子要素を1つだけ返す。 | |
161 | - * @param parent 親要素 | |
162 | - * @param tagName 子要素名 | |
163 | - * @return 子要素 | |
164 | - * @throws TogaXmlException 1つも見つからなかった | |
165 | - */ | |
166 | - public static Element getChild(Element parent, String tagName) | |
167 | - throws TogaXmlException{ | |
168 | - Element result = null; | |
169 | - | |
170 | - for(Node node = parent.getFirstChild(); | |
171 | - node != null; | |
172 | - node = node.getNextSibling() ){ | |
173 | - | |
174 | - if(node.getNodeType() != Node.ELEMENT_NODE) continue; | |
175 | - Element elem = (Element) node; | |
176 | - | |
177 | - String elemTagName = elem.getTagName(); | |
178 | - if( tagName.equals(elemTagName) ){ | |
179 | - result = elem; | |
180 | - break; | |
181 | - } | |
182 | - } | |
183 | - | |
184 | - if(result == null){ | |
185 | - String message = | |
186 | - "Elem:[" + tagName + "] was not found in " | |
187 | - +"Elem:[" + parent.getTagName() + "]"; | |
188 | - throw new TogaXmlException(message); | |
189 | - } | |
190 | - | |
191 | - return result; | |
192 | - } | |
193 | - | |
194 | - /** | |
195 | - * 親要素が指定された名前の子要素を持つか判定する。 | |
196 | - * @param parent 親要素 | |
197 | - * @param tagName 子要素名 | |
198 | - * @return 指定名の子要素が存在すればtrue | |
199 | - */ | |
200 | - public static boolean hasChild(Element parent, String tagName){ | |
201 | - for(Node node = parent.getFirstChild(); | |
202 | - node != null; | |
203 | - node = node.getNextSibling() ){ | |
204 | - | |
205 | - if(node.getNodeType() != Node.ELEMENT_NODE) continue; | |
206 | - Element elem = (Element) node; | |
207 | - | |
208 | - String elemTagName = elem.getTagName(); | |
209 | - if( tagName.equals(elemTagName) ) return true; | |
210 | - } | |
211 | - | |
212 | - return false; | |
213 | - } | |
214 | - | |
215 | - /** | |
216 | - * 指定された名前の子要素のリストを返す。 | |
217 | - * @param parent 親要素 | |
218 | - * @param childTag 子要素名 | |
219 | - * @return 子要素のリスト | |
220 | - */ | |
221 | - public static List<Element> getChildList(Element parent, | |
222 | - String childTag){ | |
223 | - List<Element> result = new LinkedList<Element>(); | |
224 | - | |
225 | - for(Node node = parent.getFirstChild(); | |
226 | - node != null; | |
227 | - node = node.getNextSibling() ){ | |
228 | - | |
229 | - if(node.getNodeType() != Node.ELEMENT_NODE) continue; | |
230 | - Element elem = (Element) node; | |
231 | - | |
232 | - String tagName = elem.getTagName(); | |
233 | - if( ! childTag.equals(tagName) ) continue; | |
234 | - | |
235 | - result.add(elem); | |
236 | - } | |
237 | - | |
238 | - return result; | |
239 | - } | |
240 | - | |
241 | - /** | |
242 | - * 指定された名前の子要素の列挙子を返す。 | |
243 | - * @param parent 親要素 | |
244 | - * @param childTag 子要素名 | |
245 | - * @return 子要素の列挙子 | |
246 | - */ | |
247 | - public static Iterator<Element> getChildIterator(Element parent, | |
248 | - String childTag){ | |
249 | - Element firstElem; | |
250 | - try{ | |
251 | - firstElem = getChild(parent, childTag); | |
252 | - }catch(TogaXmlException e){ | |
253 | - firstElem = null; | |
254 | - } | |
255 | - | |
256 | - Iterator<Element> result = new ElemIterator(firstElem); | |
257 | - | |
258 | - return result; | |
259 | - } | |
260 | - | |
261 | - /** | |
262 | - * 指定された名前の子要素のforeachを返す。 | |
263 | - * @param parent 親要素 | |
264 | - * @param childTag 子要素名 | |
265 | - * @return 子要素のforeach | |
266 | - */ | |
267 | - public static Iterable<Element> getEachChild(Element parent, | |
268 | - String childTag){ | |
269 | - final Iterator<Element> iterator = getChildIterator(parent, childTag); | |
270 | - Iterable<Element> result = new Iterable<Element>(){ | |
271 | - @Override | |
272 | - public Iterator<Element> iterator(){ | |
273 | - return iterator; | |
274 | - } | |
275 | - }; | |
276 | - return result; | |
277 | - } | |
278 | - | |
279 | - /** | |
280 | - * 要素の次の要素を返す。 | |
281 | - * @param elem 要素 | |
282 | - * @return 次の要素。なければnull | |
283 | - */ | |
284 | - public static Element nextElement(Element elem){ | |
285 | - Node nextNode = elem; | |
286 | - for(;;){ | |
287 | - nextNode = nextNode.getNextSibling(); | |
288 | - if(nextNode == null) break; | |
289 | - if(nextNode.getNodeType() == Node.ELEMENT_NODE){ | |
290 | - break; | |
291 | - } | |
292 | - } | |
293 | - | |
294 | - return (Element) nextNode; | |
295 | - } | |
296 | - | |
297 | - /** | |
298 | - * 同じ要素名を持つ次の要素を返す。 | |
299 | - * @param elem 要素 | |
300 | - * @return 次の要素。なければnull | |
301 | - */ | |
302 | - public static Element nextNamedElement(Element elem){ | |
303 | - String tagName = elem.getTagName(); | |
304 | - Element nextElem = elem; | |
305 | - for(;;){ | |
306 | - nextElem = nextElement(nextElem); | |
307 | - if(nextElem == null) break; | |
308 | - if(tagName.equals(nextElem.getTagName())) break; | |
309 | - } | |
310 | - | |
311 | - return nextElem; | |
312 | - } | |
313 | - | |
314 | - /** | |
315 | - * 同じ親要素と同じ要素名を持つ兄弟要素を列挙する列挙子。 | |
316 | - */ | |
317 | - private static final class ElemIterator implements Iterator<Element> { | |
318 | - private Element next; | |
319 | - | |
320 | - /** | |
321 | - * コンストラクタ。 | |
322 | - * @param elem 最初の要素。nullを指定すれば空列挙子となる。 | |
323 | - */ | |
324 | - ElemIterator(Element elem){ | |
325 | - super(); | |
326 | - this.next = elem; | |
327 | - } | |
328 | - | |
329 | - /** | |
330 | - * {@inheritDoc} | |
331 | - * @return {@inheritDoc} | |
332 | - */ | |
333 | - @Override | |
334 | - public boolean hasNext(){ | |
335 | - if(this.next == null) return false; | |
336 | - return true; | |
337 | - } | |
338 | - | |
339 | - /** | |
340 | - * {@inheritDoc} | |
341 | - * @return {@inheritDoc} | |
342 | - * @throws NoSuchElementException {@inheritDoc} | |
343 | - */ | |
344 | - @Override | |
345 | - public Element next() throws NoSuchElementException{ | |
346 | - if(this.next == null) throw new NoSuchElementException(); | |
347 | - Element result = this.next; | |
348 | - this.next = nextNamedElement(this.next); | |
349 | - return result; | |
350 | - } | |
351 | - | |
352 | - /** | |
353 | - * {@inheritDoc} | |
354 | - * ※ 未サポート。 | |
355 | - */ | |
356 | - @Override | |
357 | - public void remove(){ | |
358 | - throw new UnsupportedOperationException(); | |
359 | - } | |
360 | - | |
361 | - } | |
362 | - | |
363 | -} |
@@ -1,31 +0,0 @@ | ||
1 | -/* | |
2 | - * xml local resource map | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2013 olyutorskii | |
6 | - */ | |
7 | - | |
8 | -package jp.sourceforge.mikutoga.xml; | |
9 | - | |
10 | -import java.net.URI; | |
11 | - | |
12 | -/** | |
13 | - * 代用ローカルリソースの管理を行う。 | |
14 | - * <p>ネットワークを介したグローバルなリソースと、 | |
15 | - * アプリ上のローカルな代用リソースとを対応付ける。 | |
16 | - */ | |
17 | -public interface LocalXmlResource { | |
18 | - | |
19 | - /** | |
20 | - * オリジナル版XMLリソースのURIを返す。 | |
21 | - * @return オリジナル版リソースのURL。 | |
22 | - */ | |
23 | - URI getOriginalResource(); | |
24 | - | |
25 | - /** | |
26 | - * ローカル版XMLリソースのURIを返す。 | |
27 | - * @return ローカル版リソースのURL。 | |
28 | - */ | |
29 | - URI getLocalResource(); | |
30 | - | |
31 | -} |
@@ -1,195 +0,0 @@ | ||
1 | -/* | |
2 | - * proxy xml exporter | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2013 MikuToga Partners | |
6 | - */ | |
7 | - | |
8 | -package jp.sourceforge.mikutoga.xml; | |
9 | - | |
10 | -import java.io.IOException; | |
11 | - | |
12 | -/** | |
13 | - * 委譲型XMLエクスポータ。 | |
14 | - */ | |
15 | -public class ProxyXmlExporter extends AbstractXmlExporter{ | |
16 | - | |
17 | - private final XmlExporter delegate; | |
18 | - | |
19 | - | |
20 | - /** | |
21 | - * コンストラクタ。 | |
22 | - * @param delegate 委譲先 | |
23 | - */ | |
24 | - public ProxyXmlExporter(XmlExporter delegate){ | |
25 | - super(); | |
26 | - this.delegate = delegate; | |
27 | - return; | |
28 | - } | |
29 | - | |
30 | - | |
31 | - /** | |
32 | - * {@inheritDoc} | |
33 | - * @param ch {@inheritDoc} | |
34 | - * @return {@inheritDoc} | |
35 | - * @throws IOException {@inheritDoc} | |
36 | - */ | |
37 | - @Override | |
38 | - public Appendable append(char ch) throws IOException{ | |
39 | - return this.delegate.append(ch); | |
40 | - } | |
41 | - | |
42 | - /** | |
43 | - * {@inheritDoc} | |
44 | - * @param seq {@inheritDoc} | |
45 | - * @return {@inheritDoc} | |
46 | - * @throws IOException {@inheritDoc} | |
47 | - */ | |
48 | - @Override | |
49 | - public Appendable append(CharSequence seq) throws IOException{ | |
50 | - return this.delegate.append(seq); | |
51 | - } | |
52 | - | |
53 | - /** | |
54 | - * {@inheritDoc} | |
55 | - * @param seq {@inheritDoc} | |
56 | - * @param start {@inheritDoc} | |
57 | - * @param end {@inheritDoc} | |
58 | - * @return {@inheritDoc} | |
59 | - * @throws IOException {@inheritDoc} | |
60 | - */ | |
61 | - @Override | |
62 | - public Appendable append(CharSequence seq, int start, int end) | |
63 | - throws IOException{ | |
64 | - return this.delegate.append(seq, start, end); | |
65 | - } | |
66 | - | |
67 | - /** | |
68 | - * {@inheritDoc} | |
69 | - * @throws IOException {@inheritDoc} | |
70 | - */ | |
71 | - @Override | |
72 | - public void flush() throws IOException{ | |
73 | - this.delegate.flush(); | |
74 | - return; | |
75 | - } | |
76 | - | |
77 | - /** | |
78 | - * {@inheritDoc} | |
79 | - * @throws IOException {@inheritDoc} | |
80 | - */ | |
81 | - @Override | |
82 | - public void close() throws IOException{ | |
83 | - this.delegate.close(); | |
84 | - return; | |
85 | - } | |
86 | - | |
87 | - /** | |
88 | - * {@inheritDoc} | |
89 | - * @param ch {@inheritDoc} | |
90 | - * @return {@inheritDoc} | |
91 | - * @throws IOException {@inheritDoc} | |
92 | - */ | |
93 | - @Override | |
94 | - public XmlExporter putRawCh(char ch) throws IOException{ | |
95 | - return this.delegate.putRawCh(ch); | |
96 | - } | |
97 | - | |
98 | - /** | |
99 | - * {@inheritDoc} | |
100 | - * @param seq {@inheritDoc} | |
101 | - * @return {@inheritDoc} | |
102 | - * @throws IOException {@inheritDoc} | |
103 | - */ | |
104 | - @Override | |
105 | - public XmlExporter putRawText(CharSequence seq) throws IOException{ | |
106 | - return this.delegate.putRawText(seq); | |
107 | - } | |
108 | - | |
109 | - /** | |
110 | - * {@inheritDoc} | |
111 | - * @return {@inheritDoc} | |
112 | - */ | |
113 | - @Override | |
114 | - public boolean isBasicLatinOnlyOut(){ | |
115 | - return this.delegate.isBasicLatinOnlyOut(); | |
116 | - } | |
117 | - | |
118 | - /** | |
119 | - * {@inheritDoc} | |
120 | - * @param bool {@inheritDoc} | |
121 | - */ | |
122 | - @Override | |
123 | - public void setBasicLatinOnlyOut(boolean bool){ | |
124 | - this.delegate.setBasicLatinOnlyOut(bool); | |
125 | - return; | |
126 | - } | |
127 | - | |
128 | - /** | |
129 | - * {@inheritDoc} | |
130 | - * @return {@inheritDoc} | |
131 | - */ | |
132 | - @Override | |
133 | - public String getNewLine(){ | |
134 | - return this.delegate.getNewLine(); | |
135 | - } | |
136 | - | |
137 | - /** | |
138 | - * {@inheritDoc} | |
139 | - * @param newLine {@inheritDoc} | |
140 | - * @throws NullPointerException {@inheritDoc} | |
141 | - */ | |
142 | - @Override | |
143 | - public void setNewLine(String newLine) throws NullPointerException{ | |
144 | - this.delegate.setNewLine(newLine); | |
145 | - return; | |
146 | - } | |
147 | - | |
148 | - /** | |
149 | - * {@inheritDoc} | |
150 | - * @return {@inheritDoc} | |
151 | - */ | |
152 | - @Override | |
153 | - public String getIndentUnit(){ | |
154 | - return this.delegate.getIndentUnit(); | |
155 | - } | |
156 | - | |
157 | - /** | |
158 | - * {@inheritDoc} | |
159 | - * @param indUnit {@inheritDoc} | |
160 | - * @throws NullPointerException {@inheritDoc} | |
161 | - */ | |
162 | - @Override | |
163 | - public void setIndentUnit(String indUnit) throws NullPointerException{ | |
164 | - this.delegate.setIndentUnit(indUnit); | |
165 | - return; | |
166 | - } | |
167 | - | |
168 | - /** | |
169 | - * {@inheritDoc} | |
170 | - */ | |
171 | - @Override | |
172 | - public void pushNest(){ | |
173 | - this.delegate.pushNest(); | |
174 | - return; | |
175 | - } | |
176 | - | |
177 | - /** | |
178 | - * {@inheritDoc} | |
179 | - */ | |
180 | - @Override | |
181 | - public void popNest(){ | |
182 | - this.delegate.popNest(); | |
183 | - return; | |
184 | - } | |
185 | - | |
186 | - /** | |
187 | - * {@inheritDoc} | |
188 | - * @return {@inheritDoc} | |
189 | - */ | |
190 | - @Override | |
191 | - public int getIndentLevel(){ | |
192 | - return this.delegate.getIndentLevel(); | |
193 | - } | |
194 | - | |
195 | -} |
@@ -1,151 +0,0 @@ | ||
1 | -/* | |
2 | - * xml schema utility | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2013 MikuToga Partners | |
6 | - */ | |
7 | - | |
8 | -package jp.sourceforge.mikutoga.xml; | |
9 | - | |
10 | -import java.io.BufferedInputStream; | |
11 | -import java.io.IOException; | |
12 | -import java.io.InputStream; | |
13 | -import java.net.MalformedURLException; | |
14 | -import java.net.URI; | |
15 | -import java.net.URL; | |
16 | -import java.util.ArrayList; | |
17 | -import java.util.List; | |
18 | -import javax.xml.XMLConstants; | |
19 | -import javax.xml.transform.Source; | |
20 | -import javax.xml.transform.stream.StreamSource; | |
21 | -import javax.xml.validation.Schema; | |
22 | -import javax.xml.validation.SchemaFactory; | |
23 | -import org.w3c.dom.ls.LSResourceResolver; | |
24 | -import org.xml.sax.SAXException; | |
25 | - | |
26 | -/** | |
27 | - * XMLスキーマの各種ビルダ。 | |
28 | - */ | |
29 | -public final class SchemaUtil { | |
30 | - | |
31 | - /** | |
32 | - * 隠しコンストラクタ。 | |
33 | - */ | |
34 | - private SchemaUtil(){ | |
35 | - assert false; | |
36 | - throw new AssertionError(); | |
37 | - } | |
38 | - | |
39 | - | |
40 | - /** | |
41 | - * XML Schema 用のスキーマファクトリを返す。 | |
42 | - * @return スキーマファクトリ | |
43 | - */ | |
44 | - public static SchemaFactory newSchemaFactory(){ | |
45 | - SchemaFactory result = newSchemaFactory(null); | |
46 | - return result; | |
47 | - } | |
48 | - | |
49 | - /** | |
50 | - * XML Schema 用のスキーマファクトリを返す。 | |
51 | - * @param resolver カスタムリゾルバ。nullも可。 | |
52 | - * @return スキーマファクトリ | |
53 | - */ | |
54 | - public static SchemaFactory newSchemaFactory( | |
55 | - LSResourceResolver resolver ){ | |
56 | - SchemaFactory schemaFactory = | |
57 | - SchemaFactory.newInstance( | |
58 | - XMLConstants.W3C_XML_SCHEMA_NS_URI | |
59 | - ); | |
60 | - | |
61 | -// schemaFactory.setFeature(name, value); | |
62 | -// schemaFactory.setProperty(name, object); | |
63 | - | |
64 | - schemaFactory.setErrorHandler(BotherHandler.HANDLER); | |
65 | - schemaFactory.setResourceResolver(resolver); | |
66 | - | |
67 | - return schemaFactory; | |
68 | - } | |
69 | - | |
70 | - /** | |
71 | - * ローカルリソースをSourceに変換する。 | |
72 | - * @param resource ローカルリソース | |
73 | - * @return XML Source | |
74 | - * @throws MalformedURLException 不正なURI | |
75 | - * @throws IOException オープンエラー | |
76 | - */ | |
77 | - private static Source toLocalSource(LocalXmlResource resource) | |
78 | - throws MalformedURLException, IOException{ | |
79 | - URI localUri = resource.getLocalResource(); | |
80 | - URL localUrl = localUri.toURL(); | |
81 | - | |
82 | - InputStream is = localUrl.openStream(); | |
83 | - is = new BufferedInputStream(is); | |
84 | - | |
85 | - Source result = new StreamSource(is); | |
86 | - return result; | |
87 | - } | |
88 | - | |
89 | - /** | |
90 | - * ローカルリソース群をSource群に変換する。 | |
91 | - * @param resArray ローカルリソースURI並び | |
92 | - * @return XML Source並び | |
93 | - * @throws MalformedURLException 不正なURI | |
94 | - * @throws IOException オープンエラー | |
95 | - */ | |
96 | - private static Source[] toLocalSourceArray(LocalXmlResource[] resArray) | |
97 | - throws MalformedURLException, IOException{ | |
98 | - List<Source> sourceList = new ArrayList<Source>(resArray.length); | |
99 | - | |
100 | - for(LocalXmlResource resource : resArray){ | |
101 | - Source localSource = toLocalSource(resource); | |
102 | - sourceList.add(localSource); | |
103 | - } | |
104 | - | |
105 | - Source[] result = new Source[sourceList.size()]; | |
106 | - result = sourceList.toArray(result); | |
107 | - return result; | |
108 | - } | |
109 | - | |
110 | - /** | |
111 | - * ローカルスキーマをロードする。 | |
112 | - * <p>任意のリゾルバを指定可能 | |
113 | - * @param resolver リゾルバ | |
114 | - * @param resArray ローカルスキーマ情報並び | |
115 | - * @return スキーマ | |
116 | - */ | |
117 | - public static Schema newSchema(XmlResourceResolver resolver, | |
118 | - LocalXmlResource... resArray ){ | |
119 | - for(LocalXmlResource resource : resArray){ | |
120 | - resolver.putRedirected(resource); | |
121 | - } | |
122 | - | |
123 | - Source[] sources; | |
124 | - try{ | |
125 | - sources = toLocalSourceArray(resArray); | |
126 | - }catch(IOException e){ // ビルド障害 | |
127 | - assert false; | |
128 | - throw new AssertionError(e); | |
129 | - } | |
130 | - | |
131 | - SchemaFactory schemaFactory = newSchemaFactory(resolver); | |
132 | - | |
133 | - Schema result; | |
134 | - try{ | |
135 | - if(sources.length <= 0){ | |
136 | - // ドキュメント埋め込みスキーマURLにリゾルバ経由でアクセス | |
137 | - result = schemaFactory.newSchema(); | |
138 | - }else{ | |
139 | - result = schemaFactory.newSchema(sources); | |
140 | - } | |
141 | - }catch(SAXException e){ // Build error | |
142 | - assert false; | |
143 | - throw new AssertionError(e); | |
144 | - } | |
145 | - | |
146 | - // TODO: Sourceを閉めるのは誰の責務? | |
147 | - | |
148 | - return result; | |
149 | - } | |
150 | - | |
151 | -} |
@@ -1,126 +0,0 @@ | ||
1 | -/* | |
2 | - * sibling element iterator on DOM tree | |
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.NoSuchElementException; | |
12 | -import org.w3c.dom.Element; | |
13 | -import org.w3c.dom.Node; | |
14 | - | |
15 | -/** | |
16 | - * 兄弟要素間用Iterator。 | |
17 | - * <p>同じ親と名前空間とローカル名を持つ要素同士を「兄弟要素」とする。 | |
18 | - * <p>ノードの持つ名前空間がnullの場合、全ての名前空間引数にマッチする。 | |
19 | - * <p>削除操作は未サポート。 | |
20 | - */ | |
21 | -public class SiblingElemIterator implements Iterator<Element> { | |
22 | - | |
23 | - private Element next; | |
24 | - private final String nsuri; | |
25 | - private final String localName; | |
26 | - | |
27 | - | |
28 | - /** | |
29 | - * コンストラクタ。 | |
30 | - * @param first 最初の兄弟要素。nullだと一度もiterateしない。 | |
31 | - */ | |
32 | - public SiblingElemIterator(Element first){ | |
33 | - super(); | |
34 | - | |
35 | - this.next = first; | |
36 | - | |
37 | - if(this.next == null){ | |
38 | - this.nsuri = null; | |
39 | - this.localName = null; | |
40 | - }else{ | |
41 | - this.nsuri = this.next.getNamespaceURI(); | |
42 | - this.localName = this.next.getLocalName(); | |
43 | - } | |
44 | - | |
45 | - return; | |
46 | - } | |
47 | - | |
48 | - /** | |
49 | - * コンストラクタ。 | |
50 | - * <p>名前空間引数にnullが渡された場合、全ての名前空間にマッチする。 | |
51 | - * <p>ローカル名引数にnullが渡された場合、全てのローカル名にマッチする。 | |
52 | - * @param parent 親要素 | |
53 | - * @param nsuri 子要素の名前空間URI | |
54 | - * @param localName 子要素のローカル名 | |
55 | - */ | |
56 | - public SiblingElemIterator(Element parent, | |
57 | - String nsuri, | |
58 | - String localName ){ | |
59 | - super(); | |
60 | - | |
61 | - this.next = DomNsUtils.pickFirstChild(parent, nsuri, localName); | |
62 | - | |
63 | - if(this.next == null){ | |
64 | - this.nsuri = null; | |
65 | - this.localName = null; | |
66 | - }else{ | |
67 | - this.nsuri = nsuri; | |
68 | - this.localName = localName; | |
69 | - } | |
70 | - | |
71 | - return; | |
72 | - } | |
73 | - | |
74 | - | |
75 | - /** | |
76 | - * {@inheritDoc} | |
77 | - * @return {@inheritDoc} | |
78 | - */ | |
79 | - @Override | |
80 | - public boolean hasNext(){ | |
81 | - if(this.next != null) return true; | |
82 | - return false; | |
83 | - } | |
84 | - | |
85 | - /** | |
86 | - * {@inheritDoc} | |
87 | - * @return {@inheritDoc} | |
88 | - * @throws NoSuchElementException {@inheritDoc} | |
89 | - */ | |
90 | - @Override | |
91 | - public Element next() throws NoSuchElementException { | |
92 | - if(this.next == null) throw new NoSuchElementException(); | |
93 | - | |
94 | - Element result = this.next; | |
95 | - | |
96 | - Node sibNode = result; | |
97 | - do{ | |
98 | - sibNode = sibNode.getNextSibling(); | |
99 | - if(sibNode == null) break; | |
100 | - }while( ! matchElemName(sibNode) ); | |
101 | - this.next = (Element) sibNode; | |
102 | - | |
103 | - return result; | |
104 | - } | |
105 | - | |
106 | - /** | |
107 | - * 兄弟要素にふさわしい名前を持つか判定する。 | |
108 | - * @param node 判定対象 | |
109 | - * @return 兄弟にふさわしい名前を持つならtrue | |
110 | - */ | |
111 | - private boolean matchElemName(Node node){ | |
112 | - return DomNsUtils.hasNsLocalNameElem(node, | |
113 | - this.nsuri, this.localName ); | |
114 | - } | |
115 | - | |
116 | - /** | |
117 | - * {@inheritDoc} | |
118 | - * ※削除不可。 | |
119 | - * @throws UnsupportedOperationException 削除を試みたので失敗した | |
120 | - */ | |
121 | - @Override | |
122 | - public void remove() throws UnsupportedOperationException { | |
123 | - throw new UnsupportedOperationException(); | |
124 | - } | |
125 | - | |
126 | -} |
@@ -1,52 +0,0 @@ | ||
1 | -/* | |
2 | - * exception about xml | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2010 MikuToga Partners | |
6 | - */ | |
7 | - | |
8 | -package jp.sourceforge.mikutoga.xml; | |
9 | - | |
10 | -/** | |
11 | - * 意図しないXML文書を検出した際の例外。 | |
12 | - */ | |
13 | -@SuppressWarnings("serial") | |
14 | -public class TogaXmlException extends Exception{ | |
15 | - | |
16 | - /** | |
17 | - * コンストラクタ。 | |
18 | - */ | |
19 | - public TogaXmlException(){ | |
20 | - super(); | |
21 | - return; | |
22 | - } | |
23 | - | |
24 | - /** | |
25 | - * コンストラクタ。 | |
26 | - * @param message メッセージ | |
27 | - */ | |
28 | - public TogaXmlException(String message){ | |
29 | - super(message); | |
30 | - return; | |
31 | - } | |
32 | - | |
33 | - /** | |
34 | - * コンストラクタ。 | |
35 | - * @param message メッセージ | |
36 | - * @param cause 原因の例外 | |
37 | - */ | |
38 | - public TogaXmlException(String message, Throwable cause){ | |
39 | - super(message, cause); | |
40 | - return; | |
41 | - } | |
42 | - | |
43 | - /** | |
44 | - * コンストラクタ。 | |
45 | - * @param cause 原因の例外 | |
46 | - */ | |
47 | - public TogaXmlException(Throwable cause){ | |
48 | - super(cause); | |
49 | - return; | |
50 | - } | |
51 | - | |
52 | -} |
@@ -1,318 +0,0 @@ | ||
1 | -/* | |
2 | - * xml exporter | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2013 MikuToga Partners | |
6 | - */ | |
7 | - | |
8 | -package jp.sourceforge.mikutoga.xml; | |
9 | - | |
10 | -import java.io.Closeable; | |
11 | -import java.io.Flushable; | |
12 | -import java.io.IOException; | |
13 | - | |
14 | -/** | |
15 | - * XMLエクスポータ基本機能のセット。 | |
16 | - */ | |
17 | -public interface XmlExporter extends Appendable, Flushable, Closeable{ | |
18 | - | |
19 | - /** | |
20 | - * 1文字を生出力する。 | |
21 | - * @param ch 文字 | |
22 | - * @return this本体 | |
23 | - * @throws IOException 出力エラー | |
24 | - */ | |
25 | - XmlExporter putRawCh(char ch) throws IOException; | |
26 | - | |
27 | - /** | |
28 | - * 文字列を生出力する。 | |
29 | - * @param seq 文字列 | |
30 | - * @return this本体 | |
31 | - * @throws IOException 出力エラー | |
32 | - */ | |
33 | - XmlExporter putRawText(CharSequence seq) throws IOException; | |
34 | - | |
35 | - /** | |
36 | - * 空白を出力する。 | |
37 | - * @return this本体 | |
38 | - * @throws IOException 出力エラー | |
39 | - */ | |
40 | - XmlExporter sp() throws IOException; | |
41 | - | |
42 | - /** | |
43 | - * 空白を指定回数出力する。 | |
44 | - * @param count 空白回数。0以下の場合は何も出力しない。 | |
45 | - * @return this本体 | |
46 | - * @throws IOException 出力エラー | |
47 | - */ | |
48 | - XmlExporter sp(int count) throws IOException; | |
49 | - | |
50 | - /** | |
51 | - * 改行文字列を返す。 | |
52 | - * @return 改行文字列 | |
53 | - */ | |
54 | - String getNewLine(); | |
55 | - | |
56 | - /** | |
57 | - * 改行文字列を設定する。 | |
58 | - * @param newLine 改行文字列 | |
59 | - * @throws NullPointerException 引数がnull | |
60 | - */ | |
61 | - void setNewLine(String newLine) throws NullPointerException; | |
62 | - | |
63 | - /** | |
64 | - * 改行を出力する。 | |
65 | - * @return this本体 | |
66 | - * @throws IOException 出力エラー | |
67 | - */ | |
68 | - XmlExporter ln() throws IOException; | |
69 | - | |
70 | - /** | |
71 | - * 改行を指定回数出力する。 | |
72 | - * @param count 改行回数。0以下の場合は何も出力しない。 | |
73 | - * @return this本体 | |
74 | - * @throws IOException 出力エラー | |
75 | - */ | |
76 | - XmlExporter ln(int count) throws IOException; | |
77 | - | |
78 | - /** | |
79 | - * インデント単位文字列を返す。 | |
80 | - * @return インデント単位文字列 | |
81 | - */ | |
82 | - String getIndentUnit(); | |
83 | - | |
84 | - /** | |
85 | - * インデント単位文字列を設定する。 | |
86 | - * <p>デフォルトでは空白2個。 | |
87 | - * @param indUnit インデント単位文字列。 | |
88 | - * @throws NullPointerException 引数がnull | |
89 | - */ | |
90 | - void setIndentUnit(String indUnit) throws NullPointerException; | |
91 | - | |
92 | - /** | |
93 | - * インデントレベルを一段下げる。 | |
94 | - */ | |
95 | - void pushNest(); | |
96 | - | |
97 | - /** | |
98 | - * インデントレベルを一段上げる。 | |
99 | - * インデントレベル0の状態をさらに上げようとした場合、何も起こらない。 | |
100 | - */ | |
101 | - void popNest(); | |
102 | - | |
103 | - /** | |
104 | - * インデントレベルを返す。 | |
105 | - * <p>深さ1の場合1を返す。 | |
106 | - * @return インデントレベル | |
107 | - */ | |
108 | - int getIndentLevel(); | |
109 | - | |
110 | - /** | |
111 | - * インデントを出力する。 | |
112 | - * インデント単位文字列をネストレベル回数分出力する。 | |
113 | - * @return this本体 | |
114 | - * @throws IOException 出力エラー | |
115 | - */ | |
116 | - XmlExporter ind() throws IOException; | |
117 | - | |
118 | - /** | |
119 | - * BasicLatin文字だけを出力する状態か判定する。 | |
120 | - * <p>コメント部中身は対象外。 | |
121 | - * @return BasicLatin文字だけで出力するならtrue | |
122 | - */ | |
123 | - boolean isBasicLatinOnlyOut(); | |
124 | - | |
125 | - /** | |
126 | - * BasicLatin文字だけで出力するか設定する。 | |
127 | - * <p>BasicLatin以外の文字(≒日本語)を、そのまま出力するか、 | |
128 | - * 文字参照で出力するか、の設定が可能。 | |
129 | - * <p>コメント部中身は対象外。 | |
130 | - * @param bool BasicLatin文字だけで出力するならtrue | |
131 | - */ | |
132 | - void setBasicLatinOnlyOut(boolean bool); | |
133 | - | |
134 | - /** | |
135 | - * 指定された文字を16進2桁の文字参照形式で出力する。 | |
136 | - * <p>「A」は「&#x41;」になる。 | |
137 | - * <p>2桁で出力できない場合(>0x00ff)は4桁で出力する。 | |
138 | - * @param ch 文字 | |
139 | - * @return this本体 | |
140 | - * @throws IOException 出力エラー | |
141 | - * @see <a href="http://www.w3.org/TR/xml11/#NT-CharRef"> | |
142 | - * W3C XML1.1 Character Reference | |
143 | - * </a> | |
144 | - */ | |
145 | - XmlExporter putCharRef2Hex(char ch) throws IOException; | |
146 | - | |
147 | - /** | |
148 | - * 指定された文字を16進4桁の文字参照形式で出力する。 | |
149 | - * <p>「亜」は「&#x4E9C;」になる。 | |
150 | - * <p>UCS4に伴うサロゲートペアは未サポート | |
151 | - * @param ch 文字 | |
152 | - * @return this本体 | |
153 | - * @throws IOException 出力エラー | |
154 | - * @see <a href="http://www.w3.org/TR/xml11/#NT-CharRef"> | |
155 | - * W3C XML1.1 Character Reference | |
156 | - * </a> | |
157 | - */ | |
158 | - XmlExporter putCharRef4Hex(char ch) throws IOException; | |
159 | - | |
160 | - /** | |
161 | - * 要素の中身および属性値中身を出力する。 | |
162 | - * <p>XMLの構文規則を守る上で必要な各種エスケープ処理が行われる。 | |
163 | - * @param ch 文字 | |
164 | - * @return this本体 | |
165 | - * @throws IOException 出力エラー | |
166 | - */ | |
167 | - XmlExporter putCh(char ch) throws IOException; | |
168 | - | |
169 | - /** | |
170 | - * 要素の中身および属性値中身を出力する。 | |
171 | - * <p>必要に応じてXML定義済み実体文字が割り振られた文字、 | |
172 | - * コントロールコード、および非BasicLatin文字がエスケープされる。 | |
173 | - * <p>半角円通貨記号U+00A5はバックスラッシュU+005Cに置換される。 | |
174 | - * <p>連続するスペースU+0020の2文字目以降は文字参照化される。 | |
175 | - * <p>全角スペースその他空白文字は無条件に文字参照化される。 | |
176 | - * @param content 内容 | |
177 | - * @return this本体 | |
178 | - * @throws IOException 出力エラー | |
179 | - */ | |
180 | - XmlExporter putContent(CharSequence content) throws IOException; | |
181 | - | |
182 | - /** | |
183 | - * コメントの内容を出力する。 | |
184 | - * <p>コメント中の'\n'記号出現に伴い、 | |
185 | - * あらかじめ指定された改行文字が出力される。 | |
186 | - * <p>コメント中の'\n'以外のコントロールコードは | |
187 | - * Control Pictures(U+2400〜)で代替される。 | |
188 | - * <p>それ以外の非BasicLatin文字はそのまま出力される。 | |
189 | - * <p>連続するハイフン(-)記号間には強制的にスペースが挿入される。 | |
190 | - * @param comment コメント内容 | |
191 | - * @return this本体 | |
192 | - * @throws IOException 出力エラー | |
193 | - * <a href="http://www.unicode.org/charts/PDF/U2400.pdf"> | |
194 | - * Unicode 6.2 Controll Pictures | |
195 | - * </a> | |
196 | - */ | |
197 | - XmlExporter putCommentContent(CharSequence comment) throws IOException; | |
198 | - | |
199 | - /** | |
200 | - * 1行コメントを出力する。 | |
201 | - * コメント内部の頭及び末尾に空白が1つ挿入される。 | |
202 | - * @param comment コメント内容 | |
203 | - * @return this本体 | |
204 | - * @throws IOException 出力エラー | |
205 | - */ | |
206 | - XmlExporter putLineComment(CharSequence comment) throws IOException; | |
207 | - | |
208 | - /** | |
209 | - * ブロックコメントを出力する。 | |
210 | - * <p>コメント内部の頭の前に改行が出力される。 | |
211 | - * <p>コメント内部の末尾が改行でない場合、改行が挿入される。 | |
212 | - * <p>ブロックコメント末尾は改行で終わる。 | |
213 | - * <p>インデント設定は無視される。 | |
214 | - * @param comment コメント内容 | |
215 | - * @return this本体 | |
216 | - * @throws IOException 出力エラー | |
217 | - */ | |
218 | - XmlExporter putBlockComment(CharSequence comment) throws IOException; | |
219 | - | |
220 | - /** | |
221 | - * 開始タグ開き表記を出力する。 | |
222 | - * @param tagName タグ名 | |
223 | - * @return this本体 | |
224 | - * @throws IOException 出力エラー | |
225 | - */ | |
226 | - XmlExporter putOpenSTag(CharSequence tagName) throws IOException; | |
227 | - | |
228 | - /** | |
229 | - * 開始タグ閉じ表記を出力する。 | |
230 | - * @return this本体 | |
231 | - * @throws IOException 出力エラー | |
232 | - */ | |
233 | - XmlExporter putCloseSTag() throws IOException; | |
234 | - | |
235 | - /** | |
236 | - * 属性の無いシンプルな開始タグ表記を出力する。 | |
237 | - * @param tagName タグ名 | |
238 | - * @return this本体 | |
239 | - * @throws IOException 出力エラー | |
240 | - */ | |
241 | - XmlExporter putSimpleSTag(CharSequence tagName) throws IOException; | |
242 | - | |
243 | - /** | |
244 | - * 終了タグ表記を出力する。 | |
245 | - * @param tagName タグ名 | |
246 | - * @return this本体 | |
247 | - * @throws IOException 出力エラー | |
248 | - */ | |
249 | - XmlExporter putETag(CharSequence tagName) throws IOException; | |
250 | - | |
251 | - /** | |
252 | - * 属性の無い単出タグ表記を出力する。 | |
253 | - * @param tagName タグ名 | |
254 | - * @return this本体 | |
255 | - * @throws IOException 出力エラー | |
256 | - */ | |
257 | - XmlExporter putSimpleEmpty(CharSequence tagName) throws IOException; | |
258 | - | |
259 | - /** | |
260 | - * 単出タグ閉じ表記を出力する。 | |
261 | - * @return this本体 | |
262 | - * @throws IOException 出力エラー | |
263 | - */ | |
264 | - XmlExporter putCloseEmpty() throws IOException; | |
265 | - | |
266 | - /** | |
267 | - * xsd:int値をXMLスキーマ準拠の形式で出力する。 | |
268 | - * @param iVal int値 | |
269 | - * @return this本体 | |
270 | - * @throws IOException 出力エラー | |
271 | - * @see <a href="http://www.w3.org/TR/xmlschema11-2/#int"> | |
272 | - * XML Schema 1.1 Datatypes int | |
273 | - * </a> | |
274 | - */ | |
275 | - XmlExporter putXsdInt(int iVal) throws IOException; | |
276 | - | |
277 | - /** | |
278 | - * xsd:float値をXMLスキーマ準拠の形式で出力する。 | |
279 | - * @param fVal float値 | |
280 | - * @return this本体 | |
281 | - * @throws IOException 出力エラー | |
282 | - * @see <a href="http://www.w3.org/TR/xmlschema11-2/#sec-lex-float"> | |
283 | - * XML Schema 1.1 Datatypes float Lexical Mapping | |
284 | - * </a> | |
285 | - */ | |
286 | - XmlExporter putXsdFloat(float fVal) throws IOException; | |
287 | - | |
288 | - /** | |
289 | - * int型属性値を出力する。 | |
290 | - * @param attrName 属性名 | |
291 | - * @param iVal int値 | |
292 | - * @return this本体 | |
293 | - * @throws IOException 出力エラー | |
294 | - */ | |
295 | - XmlExporter putIntAttr(CharSequence attrName, int iVal) | |
296 | - throws IOException; | |
297 | - | |
298 | - /** | |
299 | - * float型属性値を出力する。 | |
300 | - * @param attrName 属性名 | |
301 | - * @param fVal float値 | |
302 | - * @return this本体 | |
303 | - * @throws IOException 出力エラー | |
304 | - */ | |
305 | - XmlExporter putFloatAttr(CharSequence attrName, float fVal) | |
306 | - throws IOException; | |
307 | - | |
308 | - /** | |
309 | - * 属性値を出力する。 | |
310 | - * @param attrName 属性名 | |
311 | - * @param content 属性内容 | |
312 | - * @return this本体 | |
313 | - * @throws IOException 出力エラー | |
314 | - */ | |
315 | - XmlExporter putAttr(CharSequence attrName, CharSequence content) | |
316 | - throws IOException; | |
317 | - | |
318 | -} |
@@ -1,472 +0,0 @@ | ||
1 | -/* | |
2 | - * xml resource resolver | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2009 olyutorskii | |
6 | - */ | |
7 | - | |
8 | -package jp.sourceforge.mikutoga.xml; | |
9 | - | |
10 | -import java.io.IOException; | |
11 | -import java.io.InputStream; | |
12 | -import java.io.Reader; | |
13 | -import java.net.URI; | |
14 | -import java.net.URISyntaxException; | |
15 | -import java.net.URL; | |
16 | -import java.util.Collections; | |
17 | -import java.util.HashMap; | |
18 | -import java.util.Map; | |
19 | -import org.w3c.dom.ls.LSInput; | |
20 | -import org.w3c.dom.ls.LSResourceResolver; | |
21 | -import org.xml.sax.EntityResolver; | |
22 | -import org.xml.sax.InputSource; | |
23 | -import org.xml.sax.SAXException; | |
24 | - | |
25 | -/** | |
26 | - * URL変換マップに従い、XML文書からの外部参照をリダイレクトする。 | |
27 | - * 相対URIはこのクラスをベースに解決される。 | |
28 | - * 主な用途は外部スキーマのリソース化など。 | |
29 | - */ | |
30 | -public class XmlResourceResolver | |
31 | - implements LSResourceResolver, EntityResolver { | |
32 | - | |
33 | - /** XML Schema. */ | |
34 | - public static final String SCHEMA_XML = | |
35 | - "http://www.w3.org/2001/xml.xsd"; | |
36 | - | |
37 | - /** XSD名前空間。 */ | |
38 | - public static final String NS_XSD = | |
39 | - "http://www.w3.org/2001/XMLSchema-instance"; | |
40 | - | |
41 | - private static final String LOCAL_SCHEMA_XML = | |
42 | - "resources/xmlspace.xsd"; | |
43 | - | |
44 | - private static final URI EMPTY_URI = URI.create(""); | |
45 | - | |
46 | - private static final Class<?> THISCLASS = XmlResourceResolver.class; | |
47 | - | |
48 | - | |
49 | - private final Map<URI, URI> uriMap; | |
50 | - | |
51 | - | |
52 | - /** | |
53 | - * コンストラクタ。 | |
54 | - */ | |
55 | - public XmlResourceResolver(){ | |
56 | - super(); | |
57 | - | |
58 | - assert this.getClass().equals(THISCLASS); | |
59 | - | |
60 | - Map<URI, URI> map; | |
61 | - map = new HashMap<URI, URI>(); | |
62 | - map = Collections.synchronizedMap(map); | |
63 | - this.uriMap = map; | |
64 | - | |
65 | - URL redirectRes = THISCLASS.getResource(LOCAL_SCHEMA_XML); | |
66 | - String redirectResName = redirectRes.toString(); | |
67 | - | |
68 | - URI originalURI = URI.create(SCHEMA_XML); | |
69 | - URI redirectURI = URI.create(redirectResName); | |
70 | - | |
71 | - putRedirectedImpl(originalURI, redirectURI); | |
72 | - | |
73 | - return; | |
74 | - } | |
75 | - | |
76 | - | |
77 | - /** | |
78 | - * 絶対URIと相対URIを合成したURIを返す。 | |
79 | - * 正規化も行われる。 | |
80 | - * @param base 絶対URIでなければならない。nullでもよい。 | |
81 | - * @param relative 絶対URIでもよいがその場合baseは無視される。null可。 | |
82 | - * @return 合成結果のURLオブジェクト。必ず絶対URIになる。 | |
83 | - * @throws java.net.URISyntaxException URIとして変。 | |
84 | - * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。 | |
85 | - */ | |
86 | - protected static URI buildBaseRelativeURI(String base, String relative) | |
87 | - throws URISyntaxException, | |
88 | - IllegalArgumentException { | |
89 | - URI baseURI; | |
90 | - if(base != null){ | |
91 | - baseURI = new URI(base); | |
92 | - if( ! baseURI.isAbsolute() ){ | |
93 | - throw new IllegalArgumentException(); | |
94 | - } | |
95 | - }else{ | |
96 | - baseURI = null; | |
97 | - } | |
98 | - | |
99 | - URI relativeURI; | |
100 | - if(relative != null){ | |
101 | - relativeURI = new URI(relative); | |
102 | - }else{ | |
103 | - relativeURI = EMPTY_URI; | |
104 | - } | |
105 | - | |
106 | - URI resultURI; | |
107 | - if(baseURI == null || relativeURI.isAbsolute()){ | |
108 | - resultURI = relativeURI; | |
109 | - }else{ | |
110 | - resultURI = baseURI.resolve(relativeURI); | |
111 | - } | |
112 | - | |
113 | - if( ! resultURI.isAbsolute() ){ | |
114 | - throw new IllegalArgumentException(); | |
115 | - } | |
116 | - | |
117 | - resultURI = resultURI.normalize(); | |
118 | - | |
119 | - return resultURI; | |
120 | - } | |
121 | - | |
122 | - /** | |
123 | - * LSInput実装を生成する。 | |
124 | - * @return LSInput実装 | |
125 | - */ | |
126 | - public static LSInput createLSInput(){ | |
127 | - LSInput input = new LSInputImpl(); | |
128 | - return input; | |
129 | - } | |
130 | - | |
131 | - | |
132 | - /** | |
133 | - * オリジナルURIとリダイレクト先のURIを登録する。 | |
134 | - * オリジナルURIへのアクセスはリダイレクトされる。 | |
135 | - * @param original オリジナルURI | |
136 | - * @param redirect リダイレクトURI | |
137 | - */ | |
138 | - private void putRedirectedImpl(URI original, URI redirect){ | |
139 | - URI oridinalNorm = original.normalize(); | |
140 | - URI redirectNorm = redirect.normalize(); | |
141 | - | |
142 | - this.uriMap.put(oridinalNorm, redirectNorm); | |
143 | - | |
144 | - return; | |
145 | - } | |
146 | - | |
147 | - /** | |
148 | - * オリジナルURIとリダイレクト先のURIを登録する。 | |
149 | - * オリジナルURIへのアクセスはリダイレクトされる。 | |
150 | - * @param original オリジナルURI | |
151 | - * @param redirect リダイレクトURI | |
152 | - */ | |
153 | - public void putRedirected(URI original, URI redirect){ | |
154 | - putRedirectedImpl(original, redirect); | |
155 | - return; | |
156 | - } | |
157 | - | |
158 | - /** | |
159 | - * ローカル版リソース参照解決を登録する。 | |
160 | - * @param lsc ローカル版リソース参照解決 | |
161 | - */ | |
162 | - public void putRedirected(LocalXmlResource lsc){ | |
163 | - URI original = lsc.getOriginalResource(); | |
164 | - if(original == null) return; | |
165 | - | |
166 | - URI local = lsc.getLocalResource(); | |
167 | - | |
168 | - putRedirected(original, local); | |
169 | - | |
170 | - return; | |
171 | - } | |
172 | - | |
173 | - /** | |
174 | - * 別リゾルバの登録内容を追加登録する。 | |
175 | - * @param other 別リゾルバ | |
176 | - */ | |
177 | - public void putRedirected(XmlResourceResolver other){ | |
178 | - this.uriMap.putAll(other.uriMap); | |
179 | - return; | |
180 | - } | |
181 | - | |
182 | - /** | |
183 | - * 登録済みリダイレクト先URIを返す。 | |
184 | - * @param original オリジナルURI | |
185 | - * @return リダイレクト先URI。未登録の場合はnull | |
186 | - */ | |
187 | - public URI getRedirected(URI original){ | |
188 | - URI keyURI = original.normalize(); | |
189 | - URI resourceURI = this.uriMap.get(keyURI); | |
190 | - return resourceURI; | |
191 | - } | |
192 | - | |
193 | - /** | |
194 | - * 登録済みリダイレクト先URIを返す。 | |
195 | - * @param original オリジナルURI | |
196 | - * @return リダイレクト先URI。未登録の場合はオリジナルを返す | |
197 | - */ | |
198 | - public URI resolveRedirected(URI original){ | |
199 | - URI result = getRedirected(original); | |
200 | - if(result == null) result = original; | |
201 | - return result; | |
202 | - } | |
203 | - | |
204 | - /** | |
205 | - * 登録済みリダイレクト先リソースの入力ストリームを得る。 | |
206 | - * @param originalURI オリジナルURI | |
207 | - * @return 入力ストリーム。リダイレクト先が未登録の場合はnull | |
208 | - * @throws java.io.IOException 入出力エラー。 | |
209 | - * もしくはリソースが見つからない。 | |
210 | - */ | |
211 | - private InputStream getXMLResourceAsStream(URI originalURI) | |
212 | - throws IOException{ | |
213 | - URI resourceURI = getRedirected(originalURI); | |
214 | - if(resourceURI == null) return null; | |
215 | - | |
216 | - URL resourceURL = resourceURI.toURL(); | |
217 | - InputStream is = resourceURL.openStream(); | |
218 | - | |
219 | - return is; | |
220 | - } | |
221 | - | |
222 | - /** | |
223 | - * {@inheritDoc} | |
224 | - * URL変換したあとの入力ソースを返す。 | |
225 | - * @param type {@inheritDoc} | |
226 | - * @param namespaceURI {@inheritDoc} | |
227 | - * @param publicId {@inheritDoc} | |
228 | - * @param systemId {@inheritDoc} | |
229 | - * @param baseURI {@inheritDoc} | |
230 | - * @return {@inheritDoc} | |
231 | - */ | |
232 | - @Override | |
233 | - public LSInput resolveResource(String type, | |
234 | - String namespaceURI, | |
235 | - String publicId, | |
236 | - String systemId, | |
237 | - String baseURI ){ | |
238 | - if(systemId == null) return null; | |
239 | - | |
240 | - URI originalURI; | |
241 | - try{ | |
242 | - originalURI = buildBaseRelativeURI(baseURI, systemId); | |
243 | - }catch(URISyntaxException e){ | |
244 | - return null; | |
245 | - } | |
246 | - | |
247 | - InputStream is; | |
248 | - try{ | |
249 | - is = getXMLResourceAsStream(originalURI); | |
250 | - }catch(IOException e){ | |
251 | - return null; | |
252 | - } | |
253 | - if(is == null) return null; | |
254 | - | |
255 | - LSInput input = createLSInput(); | |
256 | - input.setBaseURI(baseURI); | |
257 | - input.setPublicId(publicId); | |
258 | - input.setSystemId(systemId); | |
259 | - input.setByteStream(is); | |
260 | - | |
261 | - return input; | |
262 | - } | |
263 | - | |
264 | - /** | |
265 | - * {@inheritDoc} | |
266 | - * URL変換したあとの入力ソースを返す。 | |
267 | - * @param publicId {@inheritDoc} | |
268 | - * @param systemId {@inheritDoc} | |
269 | - * @return {@inheritDoc} | |
270 | - * @throws org.xml.sax.SAXException {@inheritDoc} | |
271 | - * @throws java.io.IOException {@inheritDoc} | |
272 | - */ | |
273 | - @Override | |
274 | - public InputSource resolveEntity(String publicId, String systemId) | |
275 | - throws SAXException, IOException{ | |
276 | - if(systemId == null) return null; | |
277 | - | |
278 | - URI originalUri; | |
279 | - try{ | |
280 | - originalUri = new URI(systemId); | |
281 | - }catch(URISyntaxException e){ | |
282 | - return null; | |
283 | - } | |
284 | - | |
285 | - InputStream is = getXMLResourceAsStream(originalUri); | |
286 | - if(is == null) return null; | |
287 | - | |
288 | - InputSource source = new InputSource(is); | |
289 | - source.setPublicId(publicId); | |
290 | - source.setSystemId(systemId); | |
291 | - | |
292 | - return source; | |
293 | - } | |
294 | - | |
295 | - /** | |
296 | - * JRE1.5用LSInput実装。 | |
297 | - * JRE1.6なら | |
298 | - * org.w3c.dom.ls.DOMImplementationLS#createLSInput() | |
299 | - * で生成可能かも。 | |
300 | - */ | |
301 | - private static final class LSInputImpl implements LSInput { | |
302 | - | |
303 | - private String baseURI = null; | |
304 | - private InputStream byteStream = null; | |
305 | - private boolean certifiedText = false; | |
306 | - private Reader characterStream = null; | |
307 | - private String encoding = null; | |
308 | - private String publicId = null; | |
309 | - private String stringData = null; | |
310 | - private String systemId = null; | |
311 | - | |
312 | - /** | |
313 | - * コンストラクタ。 | |
314 | - */ | |
315 | - LSInputImpl(){ | |
316 | - super(); | |
317 | - return; | |
318 | - } | |
319 | - | |
320 | - /** | |
321 | - * {@inheritDoc} | |
322 | - * @return {@inheritDoc} | |
323 | - */ | |
324 | - @Override | |
325 | - public String getBaseURI(){ | |
326 | - return this.baseURI; | |
327 | - } | |
328 | - | |
329 | - /** | |
330 | - * {@inheritDoc} | |
331 | - * @param baseURI {@inheritDoc} | |
332 | - */ | |
333 | - @Override | |
334 | - public void setBaseURI(String baseURI){ | |
335 | - this.baseURI = baseURI; | |
336 | - return; | |
337 | - } | |
338 | - | |
339 | - /** | |
340 | - * {@inheritDoc} | |
341 | - * @return {@inheritDoc} | |
342 | - */ | |
343 | - @Override | |
344 | - public InputStream getByteStream(){ | |
345 | - return this.byteStream; | |
346 | - } | |
347 | - | |
348 | - /** | |
349 | - * {@inheritDoc} | |
350 | - * @param byteStream {@inheritDoc} | |
351 | - */ | |
352 | - @Override | |
353 | - public void setByteStream(InputStream byteStream){ | |
354 | - this.byteStream = byteStream; | |
355 | - } | |
356 | - | |
357 | - /** | |
358 | - * {@inheritDoc} | |
359 | - * @return {@inheritDoc} | |
360 | - */ | |
361 | - @Override | |
362 | - public boolean getCertifiedText(){ | |
363 | - return this.certifiedText; | |
364 | - } | |
365 | - | |
366 | - /** | |
367 | - * {@inheritDoc} | |
368 | - * @param certifiedText {@inheritDoc} | |
369 | - */ | |
370 | - @Override | |
371 | - public void setCertifiedText(boolean certifiedText){ | |
372 | - this.certifiedText = certifiedText; | |
373 | - return; | |
374 | - } | |
375 | - | |
376 | - /** | |
377 | - * {@inheritDoc} | |
378 | - * @return {@inheritDoc} | |
379 | - */ | |
380 | - @Override | |
381 | - public Reader getCharacterStream(){ | |
382 | - return this.characterStream; | |
383 | - } | |
384 | - | |
385 | - /** | |
386 | - * {@inheritDoc} | |
387 | - * @param characterStream {@inheritDoc} | |
388 | - */ | |
389 | - @Override | |
390 | - public void setCharacterStream(Reader characterStream){ | |
391 | - this.characterStream = characterStream; | |
392 | - } | |
393 | - | |
394 | - /** | |
395 | - * {@inheritDoc} | |
396 | - * @return {@inheritDoc} | |
397 | - */ | |
398 | - @Override | |
399 | - public String getEncoding(){ | |
400 | - return this.encoding; | |
401 | - } | |
402 | - | |
403 | - /** | |
404 | - * {@inheritDoc} | |
405 | - * @param encoding {@inheritDoc} | |
406 | - */ | |
407 | - @Override | |
408 | - public void setEncoding(String encoding){ | |
409 | - this.encoding = encoding; | |
410 | - return; | |
411 | - } | |
412 | - | |
413 | - /** | |
414 | - * {@inheritDoc} | |
415 | - * @return {@inheritDoc} | |
416 | - */ | |
417 | - @Override | |
418 | - public String getPublicId(){ | |
419 | - return this.publicId; | |
420 | - } | |
421 | - | |
422 | - /** | |
423 | - * {@inheritDoc} | |
424 | - * @param publicId {@inheritDoc} | |
425 | - */ | |
426 | - @Override | |
427 | - public void setPublicId(String publicId){ | |
428 | - this.publicId = publicId; | |
429 | - return; | |
430 | - } | |
431 | - | |
432 | - /** | |
433 | - * {@inheritDoc} | |
434 | - * @return {@inheritDoc} | |
435 | - */ | |
436 | - @Override | |
437 | - public String getStringData(){ | |
438 | - return this.stringData; | |
439 | - } | |
440 | - | |
441 | - /** | |
442 | - * {@inheritDoc} | |
443 | - * @param stringData {@inheritDoc} | |
444 | - */ | |
445 | - @Override | |
446 | - public void setStringData(String stringData){ | |
447 | - this.stringData = stringData; | |
448 | - return; | |
449 | - } | |
450 | - | |
451 | - /** | |
452 | - * {@inheritDoc} | |
453 | - * @return {@inheritDoc} | |
454 | - */ | |
455 | - @Override | |
456 | - public String getSystemId(){ | |
457 | - return this.systemId; | |
458 | - } | |
459 | - | |
460 | - /** | |
461 | - * {@inheritDoc} | |
462 | - * @param systemId {@inheritDoc} | |
463 | - */ | |
464 | - @Override | |
465 | - public void setSystemId(String systemId){ | |
466 | - this.systemId = systemId; | |
467 | - return; | |
468 | - } | |
469 | - | |
470 | - } | |
471 | - | |
472 | -} |
@@ -1,14 +0,0 @@ | ||
1 | -/* | |
2 | - * package information for Javadoc | |
3 | - * | |
4 | - * License : The MIT License | |
5 | - * Copyright(c) 2010 MikuToga Partners | |
6 | - */ | |
7 | - | |
8 | -/** | |
9 | - * MikuToga XML共通ライブラリ。 | |
10 | - */ | |
11 | - | |
12 | -package jp.sourceforge.mikutoga.xml; | |
13 | - | |
14 | -/* EOF */ |
@@ -0,0 +1,37 @@ | ||
1 | +<?xml version="1.0" encoding="UTF-8" ?> | |
2 | + | |
3 | +<xsd:schema | |
4 | + xmlns:xsd="http://www.w3.org/2001/XMLSchema" | |
5 | + targetNamespace="http://www.w3.org/XML/1998/namespace" | |
6 | +> | |
7 | + | |
8 | + <xsd:annotation> | |
9 | + <xsd:documentation> | |
10 | + Only for using "xml:space" in XML schema definition. | |
11 | + See | |
12 | + http://www.w3.org/2001/xml.xsd | |
13 | + http://www.w3.org/2009/01/xml.xsd | |
14 | + </xsd:documentation> | |
15 | + </xsd:annotation> | |
16 | + | |
17 | + <xsd:attribute name="space"> | |
18 | + | |
19 | + <xsd:annotation> | |
20 | + <xsd:documentation> | |
21 | + about xml:space attribute | |
22 | + </xsd:documentation> | |
23 | + </xsd:annotation> | |
24 | + | |
25 | + <xsd:simpleType> | |
26 | + <xsd:restriction base="xsd:NCName"> | |
27 | + <xsd:enumeration value="default"/> | |
28 | + <xsd:enumeration value="preserve"/> | |
29 | + </xsd:restriction> | |
30 | + </xsd:simpleType> | |
31 | + | |
32 | + </xsd:attribute> | |
33 | + | |
34 | +</xsd:schema> | |
35 | + | |
36 | + | |
37 | +<!-- EOF --> |
@@ -1,37 +0,0 @@ | ||
1 | -<?xml version="1.0" encoding="UTF-8" ?> | |
2 | - | |
3 | -<xsd:schema | |
4 | - xmlns:xsd="http://www.w3.org/2001/XMLSchema" | |
5 | - targetNamespace="http://www.w3.org/XML/1998/namespace" | |
6 | -> | |
7 | - | |
8 | - <xsd:annotation> | |
9 | - <xsd:documentation> | |
10 | - Only for using "xml:space" in XML schema definition. | |
11 | - See | |
12 | - http://www.w3.org/2001/xml.xsd | |
13 | - http://www.w3.org/2009/01/xml.xsd | |
14 | - </xsd:documentation> | |
15 | - </xsd:annotation> | |
16 | - | |
17 | - <xsd:attribute name="space"> | |
18 | - | |
19 | - <xsd:annotation> | |
20 | - <xsd:documentation> | |
21 | - about xml:space attribute | |
22 | - </xsd:documentation> | |
23 | - </xsd:annotation> | |
24 | - | |
25 | - <xsd:simpleType> | |
26 | - <xsd:restriction base="xsd:NCName"> | |
27 | - <xsd:enumeration value="default"/> | |
28 | - <xsd:enumeration value="preserve"/> | |
29 | - </xsd:restriction> | |
30 | - </xsd:simpleType> | |
31 | - | |
32 | - </xsd:attribute> | |
33 | - | |
34 | -</xsd:schema> | |
35 | - | |
36 | - | |
37 | -<!-- EOF --> |
@@ -218,6 +218,20 @@ | ||
218 | 218 | return; |
219 | 219 | } |
220 | 220 | |
221 | + @Override | |
222 | + public void vmdModelSight(boolean show, int keyFrameNo){ | |
223 | + println("modelSight : frame#=" + keyFrameNo + " show=" + show); | |
224 | + return; | |
225 | + } | |
226 | + | |
227 | + @Override | |
228 | + public void vmdIkSwitch(String boneName, | |
229 | + boolean validIk, | |
230 | + int keyFrameNo ){ | |
231 | + println("IKSwitch : frame#=" + keyFrameNo + " bone=" + boneName + " valid=" + validIk); | |
232 | + return; | |
233 | + } | |
234 | + | |
221 | 235 | private void println(String msg){ |
222 | 236 | System.out.println(msg); |
223 | 237 | return; |
@@ -27,8 +27,8 @@ | ||
27 | 27 | private static final DummyHandler handler = new DummyHandler(); |
28 | 28 | |
29 | 29 | static{ |
30 | -// VMDFILE = "D:\\Test\\test.vmd"; | |
31 | - VMDFILE = "D:\\Test\\camera.vmd"; | |
30 | + VMDFILE = "D:\\Test\\test.vmd"; | |
31 | +// VMDFILE = "D:\\Test\\camera.vmd"; | |
32 | 32 | } |
33 | 33 | |
34 | 34 | private static InputStream buildSource(String fname){ |
@@ -52,6 +52,7 @@ | ||
52 | 52 | parser.setBasicHandler(handler); |
53 | 53 | parser.setLightingHandler(handler); |
54 | 54 | parser.setCameraHandler(handler); |
55 | + parser.setBoolHandler(handler); | |
55 | 56 | |
56 | 57 | return; |
57 | 58 | } |
@@ -66,7 +67,6 @@ | ||
66 | 67 | VmdParser parser = new VmdParser(source); |
67 | 68 | |
68 | 69 | setupHandler(parser); |
69 | - parser.setIgnoreName(true); | |
70 | 70 | parser.setRedundantCheck(false); |
71 | 71 | |
72 | 72 | try{ |