From 733e253a30dbebf6b94f16952832252cba5cd9a7 Mon Sep 17 00:00:00 2001 From: Olyutorskii Date: Thu, 30 Jun 2016 00:42:19 +0900 Subject: [PATCH] =?utf8?q?XML=E5=A4=96=E9=83=A8=E3=83=AA=E3=82=BD=E3=83=BC?= =?utf8?q?=E3=82=B9=E3=81=AE=E3=83=AA=E3=83=80=E3=82=A4=E3=83=AC=E3=82=AF?= =?utf8?q?=E3=83=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- CHANGELOG.txt | 2 + .../sourceforge/jindolf/archiver/JinArchiver.java | 4 + .../sourceforge/jindolf/archiver/XmlResolver.java | 249 ++++ .../archiver/resources/bbsArchive-110421.dtd | 337 +++++ .../archiver/resources/bbsArchive-110421.xsd | 1529 ++++++++++++++++++++ .../jindolf/archiver/resources/coreType-090929.xsd | 342 +++++ .../jindolf/archiver/resources/xmldummy.xsd | 43 + 7 files changed, 2506 insertions(+) create mode 100644 src/main/java/jp/sourceforge/jindolf/archiver/XmlResolver.java create mode 100644 src/main/resources/jp/sourceforge/jindolf/archiver/resources/bbsArchive-110421.dtd create mode 100644 src/main/resources/jp/sourceforge/jindolf/archiver/resources/bbsArchive-110421.xsd create mode 100644 src/main/resources/jp/sourceforge/jindolf/archiver/resources/coreType-090929.xsd create mode 100644 src/main/resources/jp/sourceforge/jindolf/archiver/resources/xmldummy.xsd diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 052f86f..e19c0a7 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -8,6 +8,8 @@ X.XXX.X (20XX-XX-XX) ・必須環境をJRE7に引き上げ。 ・Mavenプラグイン更新。 ・OSDN.JP対応。 + ・タグ出力の修正。(バグ#36356) + ・XML検証タスクが外部リソースにアクセスしないようになった。 1.502.2 (2011-04-21) ・110421版スキーマに対応。 diff --git a/src/main/java/jp/sourceforge/jindolf/archiver/JinArchiver.java b/src/main/java/jp/sourceforge/jindolf/archiver/JinArchiver.java index ddeaced..8e0f6c6 100644 --- a/src/main/java/jp/sourceforge/jindolf/archiver/JinArchiver.java +++ b/src/main/java/jp/sourceforge/jindolf/archiver/JinArchiver.java @@ -26,6 +26,7 @@ import javax.xml.validation.Validator; import jp.sourceforge.jindolf.corelib.LandDef; import jp.sourceforge.jindolf.parser.DecodeException; import jp.sourceforge.jindolf.parser.HtmlParseException; +import org.w3c.dom.ls.LSResourceResolver; import org.xml.sax.SAXException; /** @@ -171,6 +172,9 @@ public final class JinArchiver{ return; } + LSResourceResolver resolver = new XmlResolver(); + validator.setResourceResolver(resolver); + Writer writer; if(outdir != null){ writer = getFileWriter(outdir, landDef, vid); diff --git a/src/main/java/jp/sourceforge/jindolf/archiver/XmlResolver.java b/src/main/java/jp/sourceforge/jindolf/archiver/XmlResolver.java new file mode 100644 index 0000000..bd9b37a --- /dev/null +++ b/src/main/java/jp/sourceforge/jindolf/archiver/XmlResolver.java @@ -0,0 +1,249 @@ +/* + * XML resource resolver + * + * License : The MIT License + * Copyright(c) 2016 olyutorskii + */ + +package jp.sourceforge.jindolf.archiver; + +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; + +/** + * XML各種外部リソースの解決。 + */ +public class XmlResolver implements LSResourceResolver{ + + private static final String RES_XMLXSD = + "resources/xmldummy.xsd"; + private static final String RES_COREXSD = + "resources/coreType-090929.xsd"; + private static final String RES_BBSXSD = + "resources/bbsArchive-110421.xsd"; + private static final String RES_BBSDTD = + "resources/bbsArchive-110421.dtd"; + + private static final String URI_XMLXSD = + "http://www.w3.org/2001/xml.xsd"; + private static final String URI_COREXSD = + "http://jindolf.sourceforge.jp/xml/xsd/coreType-090929.xsd"; + private static final String URI_BBSXSD = + "http://jindolf.sourceforge.jp/xml/xsd/bbsArchive-110421.xsd"; + private static final String URI_BBSDTD = + "http://jindolf.sourceforge.jp/xml/dtd/bbsArchive-110421.dtd"; + + private static final DOMImplementationLS DOM_LS; + + static{ + try{ + DOM_LS = buildDomImplLS(); + }catch(ParserConfigurationException e){ + throw new ExceptionInInitializerError(e); + } + } + + + private final Map uriMap; + + + /** + * コンストラクタ。 + */ + public XmlResolver(){ + super(); + + this.uriMap = new HashMap<>(); + + setUriMap(); + + return; + } + + + /** + * DOMImplementationLS実装を生成する。 + * @return DOMImplementationLS実装 + * @throws ParserConfigurationException XML実装が満たされない + */ + private static DOMImplementationLS buildDomImplLS() + throws ParserConfigurationException{ + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + DOMImplementation domImp = builder.getDOMImplementation(); + + Object feature = domImp.getFeature("LS", "3.0"); + assert feature instanceof DOMImplementationLS; + + DOMImplementationLS result; + result = (DOMImplementationLS) feature; + + return result; + } + + /** + * 絶対URIと相対URIを合成したURIを返す。 + * 正規化も行われる。 + * @param base 絶対URIでなければならない。nullでもよい。 + * @param relative 絶対URIでもよいがその場合baseは無視される。null可。 + * @return 合成結果のURLオブジェクト。必ず絶対URIになる。 + * @throws java.net.URISyntaxException URIとして変。 + * @throws java.lang.IllegalArgumentException 絶対URIが生成できない。 + */ + public static URI buildBaseRelativeURI(String base, String relative) + throws URISyntaxException, + IllegalArgumentException { + URI baseURI; + if(base != null){ + baseURI = new URI(base); + if( ! baseURI.isAbsolute() ){ + throw new IllegalArgumentException(); + } + }else{ + baseURI = null; + } + + URI relativeURI; + if(relative != null){ + relativeURI = new URI(relative); + }else{ + relativeURI = URI.create(""); + } + + URI resultURI; + if(baseURI == null || relativeURI.isAbsolute()){ + resultURI = relativeURI; + }else{ + resultURI = baseURI.resolve(relativeURI); + } + + if( ! resultURI.isAbsolute() ){ + throw new IllegalArgumentException(); + } + + resultURI = resultURI.normalize(); + + return resultURI; + } + + + /** + * 置換マップを設定する。 + */ + private void setUriMap(){ + + try{ + putMap(URI_BBSDTD, RES_BBSDTD); + putMap(URI_BBSXSD, RES_BBSXSD); + putMap(URI_COREXSD, RES_COREXSD); + putMap(URI_XMLXSD, RES_XMLXSD); + }catch(URISyntaxException e){ + assert false; + return; + } + + return; + } + + /** + * 置換マップを設定する。 + * @param uri オリジナルURI + * @param resource リソース名 + * @throws URISyntaxException URIが変 + */ + private void putMap(String uri, String resource) + throws URISyntaxException{ + URI orig = new URI(uri); + + Class klass = getClass(); + URL resUrl = klass.getResource(resource); + URI resUri = resUrl.toURI(); + + orig = orig.normalize(); + resUri = resUri.normalize(); + + this.uriMap.put(orig, resUri); + + return; + } + + /** + * URIを解決する。 + * @param origUri オリジナルURI + * @return 解決リソースへのURI + */ + private URI resolveMap(URI origUri){ + URI key = origUri.normalize(); + URI result = this.uriMap.get(key); + + if(result == null) result = origUri; + + return result; + } + + /** + * {@inheritDoc} + * @param type {@inheritDoc} + * @param namespaceURI {@inheritDoc} + * @param publicId {@inheritDoc} + * @param systemId {@inheritDoc} + * @param baseURI {@inheritDoc} + * @return {@inheritDoc} + */ + @Override + public LSInput resolveResource(String type, + String namespaceURI, + String publicId, + String systemId, + String baseURI ){ + URI origUri; + try{ + origUri = buildBaseRelativeURI(baseURI, systemId); + }catch(URISyntaxException e){ + assert false; + return null; + } + + URI resourceUri = resolveMap(origUri); + + URL resourceUrl; + try{ + resourceUrl = resourceUri.toURL(); + }catch(MalformedURLException e){ + assert false; + return null; + } + + InputStream resourceStream; + try{ + resourceStream = resourceUrl.openStream(); + }catch(IOException e){ + assert false; + return null; + } + + LSInput result = DOM_LS.createLSInput(); + + result.setBaseURI(baseURI); + result.setPublicId(publicId); + result.setSystemId(systemId); + + result.setByteStream(resourceStream); + + return result; + } + +} diff --git a/src/main/resources/jp/sourceforge/jindolf/archiver/resources/bbsArchive-110421.dtd b/src/main/resources/jp/sourceforge/jindolf/archiver/resources/bbsArchive-110421.dtd new file mode 100644 index 0000000..8c81e8f --- /dev/null +++ b/src/main/resources/jp/sourceforge/jindolf/archiver/resources/bbsArchive-110421.dtd @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/jp/sourceforge/jindolf/archiver/resources/bbsArchive-110421.xsd b/src/main/resources/jp/sourceforge/jindolf/archiver/resources/bbsArchive-110421.xsd new file mode 100644 index 0000000..5a92eb0 --- /dev/null +++ b/src/main/resources/jp/sourceforge/jindolf/archiver/resources/bbsArchive-110421.xsd @@ -0,0 +1,1529 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +要素内のスペースとタブは +すべて保存されなければならない。 +それ以外の余分な改行とスペースとタブを入れてはならない。 +生データ記述を途中に挿入可能。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + この要素内部で使われる言語。デフォルトは「ja-JP」 +xml:base => この要素内で現れる相対URIのベース。 + 人狼BBSの運営方針によっては将来無効になる可能性もある。 +xml:space => li要素より上位要素内のホワイトスペースのパース方針。 +fullName => 村のフルネーム(ex.「F1784 日の沈まぬ村」) +vid => 村の識別ID(ex.「1784」) +commitTime => 更新時刻。24時間村なら出力するのが望ましい。 + GMTとの時差も出力するのが望ましい。 + 午後1時30分更新の例)「13:30:00+09:00」 + 時差表記がないならtimezone属性を使って + 読み込み時に補正すべき。 +state => 村の状態 +disclosure => 発言の開示状況。 + 「hot」ならプレイ真っ最中の最新日が含まれている。 + 「uncomplete」なら未開示発言を含む日が含まれている。 + 「complete」なら全発言は完全に開示されている。 +isValid => システムのトラブルでゲーム勝敗が成り立っていないと + 判断できるならfalse +landName => 国の名前。「人狼BBS:F国」など。 +formalName => 正式名称。http://homepage2.nifty.com/ninjinia/ に準ずる。 +landId => JinCoreライブラリで管理している国の識別子。F国なら「wolff」 +landPrefix => 村名の前置詞。F国なら「F」。 + 無い国も複数ある。 +locale => この国で使われている言葉・文化。 +origencoding => この国で使われているエンコーディング +timezone => この国の時刻表記で使われているタイムゾーン。 +graveIconURI => 墓アイコン画像のURI +generator => XMLを吐き出したアプリ、サブシステム、ライブラリの名前。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Avatarの識別名。 + Avatarを連想させる簡潔なアルファベット列が望ましい。(例:「gerd」) + 適当にユニークで簡素なアルファベットを割り振ってもよい。 + 短縮名で代用してもよい。 + ハイフン禁止。 +fullName => Avatarのフルネーム。(ex.「楽天家 ゲルト」) +shortName => Avatarの短縮名。(ex.「ゲルト」)スペース禁止。 +faceIconURI => 顔画像アイコンへのURI。 + プロローグから一言も発言せずに突然死した場合は省略してもよい。 +############################################################################ +]]> + + + + + + + + + + + + + + + このPeriodの種類。 +day => プロローグは0、n日目はn、n日目の次にエピローグが来たなら、 + エピローグはn+1となる。 +disclosure => 発言の開示状況。 + 「hot」ならその日はプレイ真っ最中の最新日。 + 「uncomplete」ならまだその日の未開示発言を取得していない可能性がある。 + 「complete」ならその日の全発言は完全に開示された。 +nextCommitDay => 次回更新月日。年はなし。 + GMTとの時差も出力するのが望ましい。 + 8月31日の例)「--08-31+09:00」 + 時差表記がないならlandInfo要素のtimezone属性を使って + 読み込み時に補正すべき。 +commitTime => 更新時刻。秒以下の単位は切り捨て。 + GMTとの時差も出力するのが望ましい。 + 午後1時30分更新の例)「13:30:00+09:00」 + 時差表記がないならland要素のtimezone属性を使って + 読み込み時に補正すべき。 +sourceURI => このPeriodを取り込んだときの元となったURI。 + 同じ村の同じ日でも、進行によってURIが変わることが + ありうる。 +loadedTime => このPeriodを取り込んだ時刻。 + GMTとの時差も出力するのが望ましい。 + 人狼BBSサーバからのHTTP応答内部から算出するのが望ましい。 + 無理ならローカルカレンダから。 +loadedBy => 進行中の村を参加者が読み込んだ場合、その時のログインIDを出力する。 + windows31jに由来する文字が含まれる場合もある。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + + Avatar識別子 +※ IDREFS属性を使うのやめた。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + 登場順番号。ごくまれにAvatar間で重複することあり。 +avatarId => Avatar識別子 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 処刑された人のAvatar識別子。誰も処刑されなかったら省略。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + 投票した人のAvatar識別子 +voteTo => 投票された人のAvatar識別子 +############################################################################ +]]> + + + + + + + + + + + + 突然死者のAvatar識別子 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + プレイヤーのログインID。E国では@やTypeKeyニックネームを含む全部。 + windows31jに由来する文字が含まれる場合もある。 +avatarId => Avatar識別子 +survive => 最終日まで生きていたか否か。 +role => 担当した役職 +uri => プレイヤーの指定した連絡先URI。URI条件を満たすかどうかは不明。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + 処刑された人のAvatar識別子。誰も処刑されなかったら省略。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + 被投票者 +count => 集票数 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 更新時刻 +minMembers => 最少人数 +maxMembers => 最大人数 +############################################################################ +]]> + + + + + + + + + + + + + + + + + 投票期限 +limitSpecial => 特殊行動期限 +※ 両者とも同じ値のはず。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 勝利陣営 +limitTime => エピローグ終了時刻 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + 占い師Avatarの識別子。 +target => 占われたAvatarの識別子。 +############################################################################ +]]> + + + + + + + + + + + + + + + + 狩人Avatarの識別子。 +target => 護衛されたAvatarの識別子。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 襲撃した人狼のAvatar識別子 +target => 襲撃されたAvatarの識別子 +xname => 人狼BBS XHTML上のname属性値 +time => 襲撃時刻。秒以下の単位は切り捨て。 +faceIconURI => アイコン画像URI +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + 発言種別。 +avatarId => 話したAvatarの識別子。 +xname => 村の中ではほぼユニークな識別子だが、たまに重複もありえる。 + 人狼BBS元データXHTMLのname属性の値に由来する。例:(「mes1239694501」) + 後半の数値列はエポック時からのミリ秒らしい。 +time => 発言時刻。秒以下の単位は切り捨て。時差も付けるべし。 +faceIconURI => avatar要素の顔アイコンURIと同一なら省略。 + もし指定されていたら、avatar要素の顔アイコンURIより + こちらを使ってイメージ表示した方が望ましい。 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/jp/sourceforge/jindolf/archiver/resources/coreType-090929.xsd b/src/main/resources/jp/sourceforge/jindolf/archiver/resources/coreType-090929.xsd new file mode 100644 index 0000000..f2dc65b --- /dev/null +++ b/src/main/resources/jp/sourceforge/jindolf/archiver/resources/coreType-090929.xsd @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + プロローグ中 +progress => 進行中 +epilogue => エピローグ中 +gameover => ゲーム終了 +############################################################################ +]]> + + + + + + + + + + + + + + + + プロローグ +progress => 進行中の日 +epilogue => エピローグ +############################################################################ +]]> + + + + + + + + + + + + + + + 白発言 +wolf => 赤発言 +private => 灰発言 +grave => 青発言 +############################################################################ +]]> + + + + + + + + + + + + + + + + システムイベント白 +order => システムイベント赤 +extra => システムイベント灰 +############################################################################ +]]> + + + + + + + + + + + + + + + 村人 +wolf => 人狼 +hamster => ハムスター人間 +############################################################################ +]]> + + + + + + + + + + + + + + + 村人 +wolf => 人狼 +seer => 占い師 +shaman => 霊能者 +madman => 狂人 +hunter => 狩人 +frater => 共有者 +hamster => ハムスター人間 +############################################################################ +]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/jp/sourceforge/jindolf/archiver/resources/xmldummy.xsd b/src/main/resources/jp/sourceforge/jindolf/archiver/resources/xmldummy.xsd new file mode 100644 index 0000000..2bebef1 --- /dev/null +++ b/src/main/resources/jp/sourceforge/jindolf/archiver/resources/xmldummy.xsd @@ -0,0 +1,43 @@ + + + + + + + See + http://www.w3.org/2001/xml.xsd + http://www.w3.org/2009/01/xml.xsd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.11.0