**.gif = BIN
**.jpeg = BIN
**.jpg = BIN
+**.pmd = BIN
+
X.XXX.X (20XX-XX-XX)
・Maven3対応。
+ ・XML出力改行コードの指定が可能になる。
1.102.4 (2010-10-09)
・TogaGem1.105.2のバグ修正(接続ボーンを持たない剛体の件)に対処。
+ "[1 : ONLYDYNAMICS : 物理演算 ]\n"
+ "[2 : BONEDDYNAMICS : ボーン位置合わせ ]\n";
- private String generator = "";
+ private String generator = null;
/**
* コンストラクタ。
/**
* Generatorメタ情報を設定する。
- * @param generatorArg Generatorメタ情報
- * @throws NullPointerException 引数がnull
+ * @param generatorArg Generatorメタ情報。表示したくないときはnull
*/
- public void setGenerator(String generatorArg)
- throws NullPointerException{
- if(generatorArg == null) throw new NullPointerException();
+ public void setGenerator(String generatorArg){
this.generator = generatorArg;
return;
}
putBRedContent(text);
- ln();
ind().put("</description>").ln();
if( ! hasOnlyBasicLatin(text) && isBasicLatinOnlyOut() ){
throws IOException{
int length = content.length();
- for(int pos = 0; pos < length; pos++){
- char ch = content.charAt(pos);
+ int startPos = 0;
+
+ for(int idx = 0; idx < length; idx++){
+ char ch = content.charAt(idx);
if(ch == '\n'){
- put("<br/>").ln();
- }else if(Character.isISOControl(ch)){
- putCharRef2Hex(ch);
- }else if( ! isBasicLatin(ch) && isBasicLatinOnlyOut()){
- putCharRef4Hex(ch);
- }else{
- switch(ch){
- case '&': put("&"); break;
- case '<': put("<"); break;
- case '>': put(">"); break;
- case '"': put("""); break;
- case '\'': put("'"); break;
- default: put(ch); break;
- }
+ CharSequence seq = content.subSequence(startPos, idx);
+ putContent(seq).put("<br/>").ln();
+ startPos = idx + 1;
}
}
+ if(startPos < length){
+ CharSequence seq = content.subSequence(startPos, length);
+ putContent(seq).ln();
+ }
+
return this;
}
ind().put("<credits>").ln();
ind().put("</credits>").ln(2);
- ind().put("<meta ");
- putAttr("name", "generator").sp()
- .putAttr("content", this.generator);
- put(" />").ln();
+ if(this.generator != null){
+ ind().put("<meta ");
+ putAttr("name", "generator").sp()
+ .putAttr("content", this.generator);
+ put(" />").ln();
+ }
+
ind().put("<meta ");
putAttr("name", "siteURL").sp().putAttr("content", "");
put(" />").ln();
--- /dev/null
+/*
+ * MMD model file types.
+ *
+ * License : The MIT License
+ * Copyright(c) 2012 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd2xml;
+
+/**
+ * モデルファイル種別。
+ */
+public enum ModelFileTypes {
+ /** 不明。 */
+ NONE,
+
+ /** MikuMikuDance ver7 前後で読み書きが可能なPMDファイル。 */
+ PMD,
+
+ /**
+ * スキーマ
+ * http://mikutoga.sourceforge.jp/xml/xsd/pmdxml-101009.xsd
+ * で定義されたXMLファイル。
+ */
+ XML_101009,
+
+}
--- /dev/null
+/*
+ * command line argument info
+ *
+ * License : The MIT License
+ * Copyright(c) 2012 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd2xml;
+
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * コマンドラインオプション情報。
+ */
+final class OptInfo {
+
+ private static final String EOL_LF = "\n";
+ private static final String EOL_CRLF = "\r\n";
+ private static final String EOL_DEFAULT = EOL_LF;
+
+ private static final String GENERATOR =
+ Pmd2Xml.APPNAME + ' ' + Pmd2Xml.APPVER;
+
+ private static final String HELP_CONSOLE =
+ "-h : put help message\n"
+ + "-pmd2xml : convert *.pmd to *.xml\n"
+ + "-xml2pmd : convert *.xml to *.pmd\n"
+ + "-i file : specify input file\n"
+ + "-o file : specify output file\n"
+ + "-f : force overwriting\n"
+ + "-lf : use LF as XML-newline (default)\n"
+ + "-crlf : use CR+LF as XML-newline\n"
+ + "-gen : print generator to XML (default)\n"
+ + "-nogen : do not print generator to XML\n"
+ ;
+
+ private static final String ERRMSG_UNKNOWN =
+ "Unknown option : {0}";
+ private static final String ERRMSG_NODIR =
+ "You must specify -pmd2xml or -xml2pmd.";
+ private static final String ERRMSG_NOINFILE =
+ "You must specify input file with -i.";
+ private static final String ERRMSG_NOOUTFILE =
+ "You must specify output file with -o.";
+
+
+ private boolean hasError = false;
+ private String errMsg = null;
+
+ private boolean needHelp = false;
+ private ModelFileTypes inTypes = ModelFileTypes.NONE;
+ private ModelFileTypes outTypes = ModelFileTypes.NONE;
+ private String inFilename = null;
+ private String outFilename = null;
+ private boolean overwrite = false;
+ private String newline = EOL_DEFAULT;
+ private String generator = GENERATOR;
+
+
+ /**
+ * コンストラクタ。
+ */
+ private OptInfo(){
+ super();
+ return;
+ }
+
+
+ /**
+ * コマンドラインを解析する。
+ * @param args コマンドライン
+ * @return オプション情報
+ */
+ static OptInfo parseOption(String... args){
+ OptInfo result = new OptInfo();
+
+ int argIdx = 0;
+ int argLength = args.length;
+
+ argline: while(argIdx < argLength){
+ String arg = args[argIdx];
+
+ OptSwitch opt = OptSwitch.find(arg);
+ if(opt == null){
+ String errMsg = MessageFormat.format(ERRMSG_UNKNOWN, arg);
+ result.putErrMsg(errMsg);
+ break argline;
+ }
+
+ switch(opt){
+ case OPT_HELP:
+ result.needHelp = true;
+ break argline;
+ case OPT_FORCE:
+ result.overwrite = true;
+ break;
+ case OPT_PMD2XML:
+ result.inTypes = ModelFileTypes.PMD;
+ result.outTypes = ModelFileTypes.XML_101009;
+ break;
+ case OPT_XML2PMD:
+ result.inTypes = ModelFileTypes.XML_101009;
+ result.outTypes = ModelFileTypes.PMD;
+ break;
+ case OPT_INFILE:
+ argIdx++;
+ if(argIdx >= argLength){
+ result.putErrMsg(ERRMSG_NOINFILE);
+ break argline;
+ }
+ result.inFilename = args[argIdx];
+ break;
+ case OPT_OUTFILE:
+ argIdx++;
+ if(argIdx >= argLength){
+ result.putErrMsg(ERRMSG_NOOUTFILE);
+ break argline;
+ }
+ result.outFilename = args[argIdx];
+ break;
+ case OPT_LF:
+ result.newline = EOL_LF;
+ break;
+ case OPT_CRLF:
+ result.newline = EOL_CRLF;
+ break;
+ case OPT_GEN:
+ result.generator = GENERATOR;
+ break;
+ case OPT_NOGEN:
+ result.generator = null;
+ break;
+ default:
+ assert false;
+ String errMsg = MessageFormat.format(ERRMSG_UNKNOWN, arg);
+ result.putErrMsg(errMsg);
+ break argline;
+ }
+
+ if(result.hasError()) return result;
+
+ argIdx++;
+ }
+
+ if(result.hasError()) return result;
+ if(result.needHelp()) return result;
+
+ checkResult(result);
+
+ return result;
+ }
+
+ /**
+ * オプション整合性の事後検査。
+ * @param result オプション情報
+ */
+ private static void checkResult(OptInfo result){
+ if( result.getInFileType() == ModelFileTypes.NONE
+ || result.getOutFileType() == ModelFileTypes.NONE ){
+ result.putErrMsg(ERRMSG_NODIR);
+ return;
+ }
+
+ if(result.getInFilename() == null){
+ result.putErrMsg(ERRMSG_NOINFILE);
+ return;
+ }
+
+ if(result.getOutFilename() == null){
+ result.putErrMsg(ERRMSG_NOOUTFILE);
+ return;
+ }
+
+ return;
+ }
+
+ /**
+ * コンソール提示用ヘルプ出力文字列を返す。
+ * @return オプションヘルプ文字列
+ */
+ static String getConsoleHelp(){
+ return HELP_CONSOLE;
+ }
+
+
+ /**
+ * 解析中にエラーが起きたか判定する。
+ * @return エラーが起きていればtrue
+ */
+ boolean hasError(){
+ return this.hasError;
+ }
+
+ /**
+ * エラーメッセージを返す。
+ * @return エラーメッセージ。なければnull
+ */
+ String getErrorMessage(){
+ return this.errMsg;
+ }
+
+ /**
+ * ヘルプ表示が必要か否か判定する。
+ * @return 必要ならtrue
+ */
+ boolean needHelp(){
+ return this.needHelp;
+ }
+
+ /**
+ * 入力ファイル種別を返す。
+ * @return 入力ファイル種別
+ */
+ ModelFileTypes getInFileType(){
+ return this.inTypes;
+ }
+
+ /**
+ * 出力ファイル種別を返す。
+ * @return 出力ファイル種別
+ */
+ ModelFileTypes getOutFileType(){
+ return this.outTypes;
+ }
+
+ /**
+ * 入力ファイル名を返す。
+ * @return 入力ファイル名
+ */
+ String getInFilename(){
+ return this.inFilename;
+ }
+
+ /**
+ * 出力ファイル名を返す。
+ * @return 出力ファイル名
+ */
+ String getOutFilename(){
+ return this.outFilename;
+ }
+
+ /**
+ * 上書きモードか否か返す。
+ * @return 上書きモードならtrue
+ */
+ boolean overwriteMode(){
+ return this.overwrite;
+ }
+
+ /**
+ * XML改行文字を返す。
+ * @return 改行文字
+ */
+ String getNewline(){
+ return this.newline;
+ }
+
+ /**
+ * ジェネレータ名を返す。
+ * @return ジェネレータ名。表示したくない時はnull
+ */
+ String getGenerator(){
+ return this.generator;
+ }
+
+ /**
+ * オプション解析エラー情報を設定する。
+ * @param txt エラー文字列
+ */
+ private void putErrMsg(String txt){
+ this.hasError = true;
+ this.errMsg = txt;
+ return;
+ }
+
+
+ /**
+ * オプションスイッチ群。
+ */
+ static enum OptSwitch{
+ OPT_HELP ("-h", "-help", "-?"),
+ OPT_XML2PMD ("-xml2pmd"),
+ OPT_PMD2XML ("-pmd2xml"),
+ OPT_INFILE ("-i"),
+ OPT_OUTFILE ("-o"),
+ OPT_FORCE ("-f"),
+ OPT_LF ("-lf"),
+ OPT_CRLF ("-crlf"),
+ OPT_GEN ("-gen"),
+ OPT_NOGEN ("-nogen"),
+ ;
+
+
+ /**
+ * コンストラクタ。
+ * @param cmdargs オプションスイッチパターン群
+ */
+ private OptSwitch(String... cmdargs){
+ for(String cmdarg : cmdargs){
+ MapHolder.MAP_OPT.put(cmdarg, this);
+ }
+ return;
+ }
+
+ /**
+ * パターンに合致するオプションを見つける。
+ * @param cmd パターン
+ * @return オプション。見つからなければnull
+ */
+ static OptSwitch find(String cmd){
+ OptSwitch result = MapHolder.MAP_OPT.get(cmd);
+ return result;
+ }
+
+
+ /**
+ * enumコンストラクタからクラス変数にアクセスできない文法を回避。
+ */
+ private static class MapHolder{
+ static final Map<String, OptSwitch> MAP_OPT =
+ new HashMap<String, OptSwitch>();
+ }
+
+ }
+
+}
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.PrintStream;
import java.nio.channels.FileChannel;
import java.util.Properties;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.ParserConfigurationException;
import jp.sourceforge.mikutoga.parser.MmdFormatException;
import jp.sourceforge.mikutoga.pmd.IllegalPmdDataException;
-import jp.sourceforge.mikutoga.pmd.model.PmdModel;
-import jp.sourceforge.mikutoga.pmd.model.binio.PmdExporter;
-import jp.sourceforge.mikutoga.pmd.model.binio.PmdLoader;
-import jp.sourceforge.mikutoga.pmd.model.xml.PmdXmlExporter;
-import jp.sourceforge.mikutoga.pmd.model.xml.PmdXmlResources;
-import jp.sourceforge.mikutoga.pmd.model.xml.Xml2PmdLoader;
import jp.sourceforge.mikutoga.xml.TogaXmlException;
-import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
*/
public final class Pmd2Xml {
+ /** 正常系。 */
+ public static final int EXIT_OK = 0;
+ /** ファイル入出力に起因するエラー。 */
+ public static final int EXIT_FILE = 1;
+ /** XMLフォーマットに起因するエラー。 */
+ public static final int EXIT_XML = 2;
+ /** PMDフォーマットに起因するエラー。 */
+ public static final int EXIT_PMD = 3;
+ /** 実行環境に起因するエラー。 */
+ public static final int EXIT_JREVER = 4;
+ /** オプション指定に起因するエラー。 */
+ public static final int EXIT_OPT = 5;
+ /** 内部エラー。 */
+ public static final int EXIT_INTERN = 6;
+
+ /** アプリ名。 */
+ public static final String APPNAME;
+ /** バージョン識別子。 */
+ public static final String APPVER;
+ /** ライセンス種別。 */
+ public static final String APPLICENSE;
+
private static final Class<?> THISCLASS;
- private static final String APPNAME;
- private static final String APPVER;
- private static final String APPLICENSE;
+
+ private static final PrintStream ERROUT = System.err;
static{
THISCLASS = Pmd2Xml.class;
THISCLASS.getResourceAsStream("resources/version.properties");
Properties verProps = new Properties();
try{
- verProps.load(ver);
+ try{
+ verProps.load(ver);
+ }finally{
+ ver.close();
+ }
}catch(IOException e){
throw new ExceptionInInitializerError(e);
}
APPVER = verProps.getProperty("app.version");
APPLICENSE = verProps.getProperty("app.license");
- Object dummy = new Pmd2Xml();
+ new Pmd2Xml().hashCode();
}
+
/**
- * 隠しコンストラクタ。
+ * ダミーコンストラクタ。
*/
private Pmd2Xml(){
super();
return;
}
+
/**
- * Mainエントリ。
- * @param args コマンドパラメータ
+ * VMを終了させる。
+ * @param code 終了コード
*/
- public static void main(String[] args){
- checkJRE();
-
- String inputFile = null;
- String outputFile = null;
- boolean pmd2xml = false;
- boolean xml2pmd = false;
- boolean force = false;
- int argsLen = args.length;
- for(int argIdx = 0; argIdx < argsLen; argIdx++){
- String arg = args[argIdx];
-
- if(arg.equals("-h")){
- putHelp();
- }else if(arg.equals("-pmd2xml")){
- pmd2xml = true;
- xml2pmd = false;
- }else if(arg.equals("-xml2pmd")){
- pmd2xml = false;
- xml2pmd = true;
- }else if(arg.equals("-i")){
- if(++argIdx >= argsLen){
- System.err.println("ERROR:");
- System.err.println("You need -i argument.");
- System.err.println("(-h for help)");
- System.exit(5);
- }
- inputFile = args[argIdx];
- }else if(arg.equals("-o")){
- if(++argIdx >= argsLen){
- System.err.println("ERROR:");
- System.err.println("You need -o argument.");
- System.err.println("(-h for help)");
- System.exit(5);
- }
- outputFile = args[argIdx];
- }else if(arg.equals("-f")){
- force = true;
- }else{
- System.err.println("ERROR:");
- System.err.println("Unknown option:"+arg);
- System.err.println("(-h for help)");
- System.exit(5);
- }
- }
-
- if( ( ! pmd2xml) && ( ! xml2pmd) ){
- System.err.println("ERROR:");
- System.err.println("You must specify -pmd2xml or -xml2pmd.");
- System.err.println("(-h for help)");
- System.exit(5);
- }
-
- if(inputFile == null){
- System.err.println("ERROR:");
- System.err.println("You must specify input file with -i.");
- System.err.println("(-h for help)");
- System.exit(5);
- }
-
- if(outputFile == null){
- System.err.println("ERROR:");
- System.err.println("You must specify output file with -o.");
- System.err.println("(-h for help)");
- System.exit(5);
- }
+ private static void exit(int code){
+ System.exit(code);
+ return;
+ }
- File iFile = new File(inputFile);
- if( (! iFile.exists()) || (! iFile.isFile()) ){
- System.err.println("ERROR:");
- System.err.println("Can't find input file:"
- + iFile.getAbsolutePath());
- System.err.println("(-h for help)");
- System.exit(1);
- }
+ /**
+ * 標準エラー出力へ例外情報出力。
+ * @param ex 例外
+ * @param dumpStack スタックトレースを出力するならtrue
+ */
+ private static void errPrintln(Throwable ex, boolean dumpStack){
+ String text = ex.toString();
+ ERROUT.println(text);
- if( ! force ){
- File oFile = new File(outputFile);
- if(oFile.exists()){
- System.err.println("ERROR:");
- System.err.println(oFile.getAbsolutePath()
- + " already exists.");
- System.err.println("If you want to overwrite, use -f.");
- System.err.println("(-h for help)");
- System.exit(1);
- }
- }else{
- File oFile = new File(outputFile);
- if(oFile.exists()){
- if( ! oFile.isFile()){
- System.err.println("ERROR:");
- System.err.println(oFile.getAbsolutePath()
- + " is not file.");
- System.err.println("(-h for help)");
- System.exit(1);
- }
- }
+ if(dumpStack){
+ ex.printStackTrace(ERROUT);
}
- try{
- if(pmd2xml) pmd2xml(inputFile, outputFile);
- else xml2pmd(inputFile, outputFile);
- }catch(IOException e){
- ioError(e);
- }catch(ParserConfigurationException e){
- internalError(e);
- }catch(IllegalPmdDataException e){
- internalError(e);
- }catch(MmdFormatException e){
- pmdError(e);
- }catch(TogaXmlException e){
- xmlError(e);
- }catch(SAXException e){
- xmlError(e);
- }
+ return;
+ }
- System.exit(0);
+ /**
+ * 標準エラー出力へ例外情報出力。
+ * @param ex 例外
+ */
+ private static void errPrintln(Throwable ex){
+ errPrintln(ex, false);
+ return;
+ }
+ /**
+ * 共通エラーメッセージを出力する。
+ * @param text 個別メッセージ
+ */
+ private static void errMsg(String text){
+ ERROUT.println("ERROR:");
+ ERROUT.println(text);
+ ERROUT.println("(-h for help)");
return;
}
* @param ex 例外
*/
private static void ioError(Throwable ex){
- System.err.println(ex);
- System.exit(1);
+ errPrintln(ex);
+ exit(EXIT_FILE);
}
/**
* @param ex 例外
*/
private static void xmlError(Throwable ex){
- System.err.println(ex);
- System.exit(2);
+ errPrintln(ex);
+ exit(EXIT_XML);
}
/**
* @param ex 例外
*/
private static void pmdError(Throwable ex){
- System.err.println(ex);
- ex.printStackTrace(System.err);
- System.exit(3);
+ errPrintln(ex, true);
+ exit(EXIT_PMD);
}
/**
* @param ex 例外
*/
private static void internalError(Throwable ex){
- System.err.println(ex);
- ex.printStackTrace(System.err);
- System.exit(4);
+ errPrintln(ex, true);
+ exit(EXIT_INTERN);
}
/**
private static void checkJRE(){
Package jrePackage = java.lang.Object.class.getPackage();
if( ! jrePackage.isCompatibleWith("1.6")){
- System.err.println("You need JRE 1.6 or later.");
- System.exit(4);
+ ERROUT.println("You need JRE 1.6 or later.");
+ exit(EXIT_JREVER);
}
return;
}
* ヘルプメッセージを出力してVMを終了させる。
*/
private static void putHelp(){
- System.err.println(APPNAME + ' ' + APPVER );
- System.err.println(" License : " + APPLICENSE);
- System.err.println(" http://mikutoga.sourceforge.jp/");
- System.err.println();
- System.err.println("-h : put help massage");
- System.err.println("-pmd2xml : convert *.pmd to *.xml");
- System.err.println("-xml2pmd : convert *.xml to *.pmd");
- System.err.println("-i file : specify input file");
- System.err.println("-o file : specify output file");
- System.err.println("-f : force overwriting");
- System.exit(0);
- return;
- }
+ StringBuilder appInfo = new StringBuilder();
+ String indent = " ";
- /**
- * PMD->XML変換を行う。
- * @param inputFile 入力ファイル名
- * @param outputFile 出力ファイル名
- * @throws IOException 入出力エラー
- * @throws MmdFormatException 不正なPMDファイル
- * @throws IllegalPmdDataException 不正なモデルデータ
- */
- private static void pmd2xml(String inputFile, String outputFile)
- throws IOException, MmdFormatException, IllegalPmdDataException{
- File iFile = new File(inputFile);
- InputStream is = new FileInputStream(iFile);
- is = new BufferedInputStream(is);
- PmdModel model = pmdRead(is);
- is.close();
+ appInfo.append(APPNAME).append(' ').append(APPVER)
+ .append('\n');
+ appInfo.append(indent)
+ .append("License").append(" : ").append(APPLICENSE)
+ .append('\n');
+ appInfo.append(indent)
+ .append("http://mikutoga.sourceforge.jp/")
+ .append('\n');
- File oFile = new File(outputFile);
- trunc(oFile);
- OutputStream ostream;
- ostream = new FileOutputStream(oFile, false);
- ostream = new BufferedOutputStream(ostream);
- xmlOut(model, ostream);
- ostream.close();
-
- return;
- }
-
- /**
- * XML->PMD変換を行う。
- * @param inputFile 入力ファイル名
- * @param outputFile 出力ファイル名
- * @throws IOException 入出力エラー
- * @throws ParserConfigurationException XML構成のエラー
- * @throws SAXException 不正なXMLファイル
- * @throws TogaXmlException 不正なXMLファイル
- * @throws IllegalPmdDataException 不正なPMDモデルデータ
- */
- private static void xml2pmd(String inputFile, String outputFile)
- throws IOException,
- ParserConfigurationException,
- SAXException,
- TogaXmlException,
- IllegalPmdDataException {
- File iFile = new File(inputFile);
- InputStream is = new FileInputStream(iFile);
- is = new BufferedInputStream(is);
- InputSource source = new InputSource(is);
- PmdModel model = xmlRead(source);
- is.close();
-
- File oFile = new File(outputFile);
- trunc(oFile);
- OutputStream ostream;
- ostream = new FileOutputStream(oFile, false);
- ostream = new BufferedOutputStream(ostream);
- pmdOut(model, ostream);
- ostream.close();
+ ERROUT.println(appInfo.toString());
+ ERROUT.println(OptInfo.getConsoleHelp());
return;
}
}
/**
- * PMDファイルからモデルデータを読み込む。
- * @param is 入力ストリーム
- * @return モデルデータ
- * @throws IOException 入力エラー
- * @throws MmdFormatException 不正なPMDファイルフォーマット
+ * 入力ストリームを準備する。
+ * @param fileName 入力ファイル名
+ * @return 入力ストリーム
*/
- private static PmdModel pmdRead(InputStream is)
- throws IOException, MmdFormatException{
- PmdLoader loader = new PmdLoader(is);
+ private static InputStream openInfile(String fileName){
+ File inFile = new File(fileName);
- PmdModel model = loader.load();
+ if( (! inFile.exists()) || (! inFile.isFile()) ){
+ String absPath = inFile.getAbsolutePath();
+ errMsg("Can't find input file:" + absPath);
+ exit(EXIT_FILE);
+ }
- return model;
- }
+ InputStream is = null;
+ try{
+ is = new FileInputStream(inFile);
+ }catch(FileNotFoundException e){
+ ioError(e);
+ assert false;
+ }
- /**
- * XMLファイルからモデルデータを読み込む。
- * @param source 入力ソース
- * @return モデルデータ
- * @throws IOException 入力エラー
- * @throws ParserConfigurationException XML構成エラー
- * @throws SAXException XML構文エラー
- * @throws TogaXmlException 不正なXMLデータ
- */
- private static PmdModel xmlRead(InputSource source)
- throws IOException,
- ParserConfigurationException,
- SAXException,
- TogaXmlException {
- DocumentBuilder builder =
- PmdXmlResources.newBuilder(XmlHandler.HANDLER);
- Xml2PmdLoader loader = new Xml2PmdLoader(builder);
-
- PmdModel model = loader.parse(source);
-
- return model;
+ is = new BufferedInputStream(is);
+
+ return is;
}
/**
- * モデルデータをPMDファイルに出力する。
- * @param model モデルデータ
- * @param ostream 出力ストリーム
- * @throws IOException 出力エラー
- * @throws IllegalPmdDataException 不正なモデルデータ
+ * 出力ストリームを準備する。
+ * @param fileName 出力ファイル名
+ * @param overWrite 頭から上書きして良ければtrue
+ * @return 出力ストリーム
*/
- private static void pmdOut(PmdModel model, OutputStream ostream)
- throws IOException, IllegalPmdDataException{
- PmdExporter exporter = new PmdExporter(ostream);
- exporter.dumpPmdModel(model);
- ostream.close();
- return;
+ private static OutputStream openOutfile(String fileName,
+ boolean overWrite) {
+ File outFile = new File(fileName);
+
+ if(outFile.exists()){
+ String absPath = outFile.getAbsolutePath();
+ if( ! outFile.isFile() ){
+ String msg = absPath + " is not file.";
+ errMsg(msg);
+ exit(EXIT_FILE);
+ }else if( ! overWrite ){
+ String msg =
+ absPath + " already exists.\n"
+ + "If you want to overwrite, use -f.";
+ errMsg(msg);
+ exit(EXIT_FILE);
+ }
+ }
+
+ try{
+ trunc(outFile);
+ }catch(IOException e){
+ ioError(e);
+ }
+
+ OutputStream os = null;
+ try{
+ os = new FileOutputStream(outFile);
+ }catch(FileNotFoundException e){
+ ioError(e);
+ assert false;
+ }
+
+ os = new BufferedOutputStream(os);
+
+ return os;
}
/**
- * モデルデータをXMLファイルに出力する。
- * @param model モデルデータ
- * @param ostream 出力ストリーム
- * @throws IOException 出力エラー
- * @throws IllegalPmdDataException 不正なモデルデータ
+ * Mainエントリ。
+ * @param args コマンドパラメータ
*/
- private static void xmlOut(PmdModel model, OutputStream ostream)
- throws IOException, IllegalPmdDataException{
- PmdXmlExporter exporter = new PmdXmlExporter(ostream);
- exporter.setNewLine("\r\n");
- exporter.setGenerator(APPNAME + ' ' + APPVER);
- exporter.putPmdModel(model);
- exporter.close();
+ public static void main(String[] args){
+ checkJRE();
+
+ Pmd2XmlConv converter = new Pmd2XmlConv();
+
+ OptInfo optInfo = OptInfo.parseOption(args);
+ if(optInfo.needHelp()){
+ putHelp();
+ exit(EXIT_OK);
+ }else if(optInfo.hasError()){
+ String optErrMsg = optInfo.getErrorMessage();
+ errMsg(optErrMsg);
+ exit(EXIT_OPT);
+ }
+
+ String inputFile = optInfo.getInFilename();
+ String outputFile = optInfo.getOutFilename();
+ boolean overwrite = optInfo.overwriteMode();
+
+ InputStream is = openInfile(inputFile);
+ OutputStream os = openOutfile(outputFile, overwrite);
+
+ converter.setInType(optInfo.getInFileType());
+ converter.setOutType(optInfo.getOutFileType());
+
+ converter.setNewline(optInfo.getNewline());
+ converter.setGenerator(optInfo.getGenerator());
+
+ try{
+ converter.convert(is, os);
+ }catch(IOException e){
+ ioError(e);
+ }catch(IllegalPmdDataException e){
+ internalError(e);
+ }catch(MmdFormatException e){
+ pmdError(e);
+ }catch(TogaXmlException e){
+ xmlError(e);
+ }catch(SAXException e){
+ xmlError(e);
+ }
+
+ try{
+ is.close();
+ try{
+ os.close();
+ }catch(IOException e){
+ ioError(e);
+ }
+ }catch(IOException e){
+ ioError(e);
+ }
+
+ exit(EXIT_OK);
+
return;
}
--- /dev/null
+/*
+ * pmd 2 xml converter
+ *
+ * License : The MIT License
+ * Copyright(c) 2010 MikuToga Partners
+ */
+
+package jp.sourceforge.mikutoga.pmd2xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.ParserConfigurationException;
+import jp.sourceforge.mikutoga.parser.MmdFormatException;
+import jp.sourceforge.mikutoga.pmd.IllegalPmdDataException;
+import jp.sourceforge.mikutoga.pmd.model.PmdModel;
+import jp.sourceforge.mikutoga.pmd.model.binio.PmdExporter;
+import jp.sourceforge.mikutoga.pmd.model.binio.PmdLoader;
+import jp.sourceforge.mikutoga.pmd.model.xml.PmdXmlExporter;
+import jp.sourceforge.mikutoga.pmd.model.xml.PmdXmlResources;
+import jp.sourceforge.mikutoga.pmd.model.xml.Xml2PmdLoader;
+import jp.sourceforge.mikutoga.xml.TogaXmlException;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * PMD-XML間コンバータ本体。
+ */
+public class Pmd2XmlConv {
+
+ private ModelFileTypes inTypes = ModelFileTypes.NONE;
+ private ModelFileTypes outTypes = ModelFileTypes.NONE;
+ private String newLine = "\r\n";
+ private String generator = null;
+
+ private final DocumentBuilder builder;
+
+
+ /**
+ * コンストラクタ。
+ */
+ public Pmd2XmlConv(){
+ super();
+
+ try{
+ this.builder = PmdXmlResources.newBuilder(XmlHandler.HANDLER);
+ }catch(SAXException e){
+ throw new AssertionError(e);
+ }catch(ParserConfigurationException e){
+ throw new AssertionError(e);
+ }
+
+ return;
+ }
+
+
+ /**
+ * 入力ファイル種別を設定する。
+ * @param type ファイル種別
+ */
+ public void setInType(ModelFileTypes type){
+ if(type == null) throw new NullPointerException();
+ this.inTypes = type;
+ return;
+ }
+
+ /**
+ * 入力ファイル種別を返す。
+ * @return ファイル種別
+ */
+ public ModelFileTypes getInTypes(){
+ return this.inTypes;
+ }
+
+ /**
+ * 出力ファイル種別を設定する。
+ * @param type ファイル種別
+ */
+ public void setOutType(ModelFileTypes type){
+ if(type == null) throw new NullPointerException();
+ this.outTypes = type;
+ return;
+ }
+
+ /**
+ * 出力ファイル種別を返す。
+ * @return ファイル種別
+ */
+ public ModelFileTypes getOutTypes(){
+ return this.outTypes;
+ }
+
+ /**
+ * XML出力用改行文字列を設定する。
+ * @param newline 改行文字
+ */
+ public void setNewline(String newline){
+ this.newLine = newline;
+ return;
+ }
+
+ /**
+ * XML出力用改行文字列を返す。
+ * @return 改行文字
+ */
+ public String getNewLine(){
+ return this.newLine;
+ }
+
+ /**
+ * ジェネレータ名を設定する。
+ * @param generator ジェネレータ名。表示したくない場合はnull
+ */
+ public void setGenerator(String generator){
+ this.generator = generator;
+ return;
+ }
+
+ /**
+ * ジェネレータ名を返す。
+ * @return ジェネレータ名。非表示の場合はnullを返す。
+ */
+ public String getGenerator(){
+ return this.generator;
+ }
+
+ /**
+ * ファイル変換を行う。
+ * @param is 入力ストリーム
+ * @param os 出力ストリーム
+ * @throws IOException 入力エラー
+ * @throws MmdFormatException フォーマットエラー
+ * @throws SAXException XMLエラー
+ * @throws TogaXmlException XMLエラー
+ * @throws IllegalPmdDataException 内部エラー
+ */
+ public void convert(InputStream is, OutputStream os)
+ throws IOException,
+ MmdFormatException,
+ SAXException,
+ TogaXmlException,
+ IllegalPmdDataException {
+ PmdModel model = readModel(is);
+ writeModel(model, os);
+ return;
+ }
+
+ /**
+ * モデルファイルを読み込む。
+ * @param is 入力ストリーム
+ * @return モデルデータ
+ * @throws IOException 入力エラー
+ * @throws MmdFormatException フォーマットエラー
+ * @throws SAXException XMLエラー
+ * @throws TogaXmlException XMLエラー
+ */
+ public PmdModel readModel(InputStream is)
+ throws IOException,
+ MmdFormatException,
+ SAXException,
+ TogaXmlException {
+ PmdModel model = null;
+ switch(this.inTypes){
+ case PMD:
+ model = pmdRead(is);
+ break;
+ case XML_101009:
+ model = xmlRead(is);
+ break;
+ default:
+ assert false;
+ break;
+ }
+ return model;
+ }
+
+ /**
+ * モデルファイルを出力する。
+ * @param model モデルデータ
+ * @param os 出力ストリーム
+ * @throws IOException 出力エラー
+ * @throws IllegalPmdDataException データの不備
+ */
+ public void writeModel(PmdModel model, OutputStream os)
+ throws IOException,
+ IllegalPmdDataException {
+ switch(this.outTypes){
+ case PMD:
+ pmdOut(model, os);
+ break;
+ case XML_101009:
+ xmlOut(model, os);
+ break;
+ default:
+ assert false;
+ break;
+ }
+ }
+
+ /**
+ * PMDファイルからモデルデータを読み込む。
+ * @param is 入力ストリーム
+ * @return モデルデータ
+ * @throws IOException 入力エラー
+ * @throws MmdFormatException 不正なPMDファイルフォーマット
+ */
+ private PmdModel pmdRead(InputStream is)
+ throws IOException, MmdFormatException{
+ PmdLoader loader = new PmdLoader(is);
+ PmdModel model = loader.load();
+ return model;
+ }
+
+ /**
+ * XMLファイルからモデルデータを読み込む。
+ * @param is 入力ストリーム
+ * @return モデルデータ
+ * @throws IOException 入力エラー
+ * @throws SAXException XML構文エラー
+ * @throws TogaXmlException 不正なXMLデータ
+ */
+ private PmdModel xmlRead(InputStream is)
+ throws IOException,
+ SAXException,
+ TogaXmlException {
+ InputSource source = new InputSource(is);
+ PmdModel result = xmlRead(source);
+ return result;
+ }
+
+ /**
+ * XMLファイルからモデルデータを読み込む。
+ * @param source 入力ソース
+ * @return モデルデータ
+ * @throws IOException 入力エラー
+ * @throws SAXException XML構文エラー
+ * @throws TogaXmlException 不正なXMLデータ
+ */
+ private PmdModel xmlRead(InputSource source)
+ throws IOException,
+ SAXException,
+ TogaXmlException {
+ Xml2PmdLoader loader = new Xml2PmdLoader(this.builder);
+ PmdModel model = loader.parse(source);
+ return model;
+ }
+
+ /**
+ * モデルデータをPMDファイルに出力する。
+ * @param model モデルデータ
+ * @param ostream 出力ストリーム
+ * @throws IOException 出力エラー
+ * @throws IllegalPmdDataException 不正なモデルデータ
+ */
+ private void pmdOut(PmdModel model, OutputStream ostream)
+ throws IOException, IllegalPmdDataException{
+ PmdExporter exporter = new PmdExporter(ostream);
+ exporter.dumpPmdModel(model);
+ ostream.close();
+ return;
+ }
+
+ /**
+ * モデルデータをXMLファイルに出力する。
+ * @param model モデルデータ
+ * @param ostream 出力ストリーム
+ * @throws IOException 出力エラー
+ * @throws IllegalPmdDataException 不正なモデルデータ
+ */
+ private void xmlOut(PmdModel model, OutputStream ostream)
+ throws IOException, IllegalPmdDataException{
+ PmdXmlExporter exporter = new PmdXmlExporter(ostream);
+ exporter.setNewLine(this.newLine);
+ exporter.setGenerator(this.generator);
+ exporter.putPmdModel(model);
+ exporter.close();
+ return;
+ }
+
+}
--- /dev/null
+/*
+ */
+
+package testdata;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import jp.sourceforge.mikutoga.pmd2xml.ModelFileTypes;
+import jp.sourceforge.mikutoga.pmd2xml.Pmd2XmlConv;
+
+import static org.junit.Assert.*;
+
+/**
+ *
+ */
+public class CnvAssert {
+
+ /**
+ * テスト出力用テンポラリファイルの生成。
+ * テスト終了時(VM終了時)に消える。
+ * @return テンポラリファイル
+ * @throws IOException エラー
+ */
+ public static File openTempFile() throws IOException{
+ File file = File.createTempFile("pmd2xml", null);
+ file.deleteOnExit();
+ return file;
+ }
+
+ /**
+ * XMLリソースをPMDに変換した結果がPMDリソースに等しいと表明する。
+ * @param klass リソース元クラス
+ * @param xmlResource XMLリソース名
+ * @param expPmdResource PMDリソース名
+ * @throws Exception エラー
+ */
+ public static void assertXml2Pmd(
+ Class<?> klass,
+ String xmlResource,
+ String expPmdResource )
+ throws Exception{
+ InputStream xmlis =
+ klass.getResourceAsStream(xmlResource);
+ assertNotNull(xmlis);
+ xmlis = new BufferedInputStream(xmlis);
+
+ File destFile = openTempFile();
+ OutputStream destOut;
+ destOut = new FileOutputStream(destFile);
+ destOut = new BufferedOutputStream(destOut);
+
+ Pmd2XmlConv converter = new Pmd2XmlConv();
+ converter.setInType(ModelFileTypes.XML_101009);
+ converter.setOutType(ModelFileTypes.PMD);
+ converter.setNewline("\n");
+
+ converter.convert(xmlis, destOut);
+
+ xmlis.close();
+ destOut.close();
+
+ assertSameFile(klass, expPmdResource, destFile);
+
+ return;
+ }
+
+ /**
+ * PMDリソースをXMLに変換した結果がXMLリソースに等しいと表明する。
+ * @param klass リソース元クラス
+ * @param pmdResource PMDリソース名
+ * @param expXmlResource XMLリソース名
+ * @throws Exception エラー
+ */
+ public static void assertPmd2Xml(
+ Class<?> klass,
+ String pmdResource,
+ String expXmlResource )
+ throws Exception{
+ InputStream pmdis =
+ klass.getResourceAsStream(pmdResource);
+ assertNotNull(pmdis);
+ pmdis = new BufferedInputStream(pmdis);
+
+ File destFile = openTempFile();
+ OutputStream destOut;
+ destOut = new FileOutputStream(destFile);
+ destOut = new BufferedOutputStream(destOut);
+
+ Pmd2XmlConv converter = new Pmd2XmlConv();
+ converter.setInType(ModelFileTypes.PMD);
+ converter.setOutType(ModelFileTypes.XML_101009);
+ converter.setNewline("\n");
+ converter.setGenerator(null);
+
+ converter.convert(pmdis, destOut);
+
+ pmdis.close();
+ destOut.close();
+
+ assertSameFile(klass, expXmlResource, destFile);
+
+ return;
+ }
+
+ /**
+ * リソースとファイルの内容が等しいと表明する。
+ * @param klass リソース元クラス
+ * @param resourceName リソース名
+ * @param resFile ファイル
+ * @throws IOException 入力エラー
+ */
+ public static void assertSameFile(
+ Class<?> klass,
+ String resourceName,
+ File resFile )
+ throws IOException{
+ InputStream expis =
+ klass.getResourceAsStream(resourceName);
+ assertNotNull(expis);
+
+ InputStream resIn = new FileInputStream(resFile);
+
+ try{
+ assertSameStream(expis, resIn);
+ }finally{
+ expis.close();
+ resIn.close();
+ }
+
+ return;
+ }
+
+ /**
+ * 2つの入力ストリーム内容が等しいと表明する。
+ * @param expIn 期待する入力ストリーム
+ * @param resIn 結果入力ストリーム
+ * @throws IOException 入力エラー
+ */
+ public static void assertSameStream(InputStream expIn, InputStream resIn)
+ throws IOException{
+ InputStream expis = new BufferedInputStream(expIn);
+ InputStream resis = new BufferedInputStream(resIn);
+
+
+ for(;;){
+ int expCh = expis.read();
+ int resCh = resis.read();
+
+ assertEquals(expCh, resCh);
+
+ if(expCh < 0) break;
+ }
+
+ return;
+ }
+
+}
--- /dev/null
+/*
+ */
+
+package testdata.charset;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static testdata.CnvAssert.*;
+
+/**
+ *
+ */
+public class CharsetTest {
+
+ static Class<?> THISCLASS = CharsetTest.class;
+
+ public CharsetTest() {
+ assert this.getClass() == THISCLASS;
+ return;
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void pmd2xml() throws Exception{
+ System.out.println("pmd2xml");
+ assertPmd2Xml(THISCLASS, "test.pmd", "result.xml");
+ return;
+ }
+
+ @Test
+ public void xml2pmd() throws Exception{
+ System.out.println("xml2pmd");
+ assertXml2Pmd(THISCLASS, "source.xml", "test.pmd");
+ return;
+ }
+
+}
--- /dev/null
+/*
+ */
+
+package testdata.minimum;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static testdata.CnvAssert.*;
+
+/**
+ *
+ */
+public class MinimumTest {
+
+ static Class<?> THISCLASS = MinimumTest.class;
+
+ public MinimumTest() {
+ assert this.getClass() == THISCLASS;
+ return;
+ }
+
+ @BeforeClass
+ public static void setUpClass() {
+ }
+
+ @AfterClass
+ public static void tearDownClass() {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ @Test
+ public void pmd2xml() throws Exception{
+ System.out.println("pmd2xml");
+ assertPmd2Xml(THISCLASS, "test.pmd", "test.xml");
+ return;
+ }
+
+ @Test
+ public void xml2pmd() throws Exception{
+ System.out.println("xml2pmd");
+ assertXml2Pmd(THISCLASS, "test.xml", "test.pmd");
+ return;
+ }
+
+}
--- /dev/null
+文字集合、エンコーディング、XML文字エスケープ、空白文字に関するテストデータ。
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+ MikuMikuDance
+ model-data(*.pmd) on XML
+-->
+
+
+<!-- a A 9 亜'" -->
+<pmdModel
+ xmlns="http://mikutoga.sourceforge.jp/xml/ns/pmdxml/101009"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://mikutoga.sourceforge.jp/xml/ns/pmdxml/101009 http://mikutoga.sourceforge.jp/xml/xsd/pmdxml-101009.xsd"
+ schemaVersion="101009"
+
+ name="a A  9 亜'""
+>
+
+
+<description>
+azAZAZ0909あアアゑヵヶΩωЖж<br/>
+┐└漢峠凜熙<br/>
+ヴウ゛ヴパハ゜パ<br/>
+壺壷尭堯<br/>
+\\\¥<br/>
+髙⑨≒∵¬㈱Σ<br/>
+#$[\]^{|}~<br/>
+cdata'"&<>test<br/>
+<!--fake comment--><br/>
+A B  C	D		E F  GHI
+</description>
+<!--
+azAZAZ0909あアアゑヵヶΩωЖж
+┐└漢峠凜熙
+ヴウ゛ヴパハ゜パ
+壺壷尭堯
+\\\¥
+髙⑨≒∵¬㈱Σ
+#$[\]^{|}~
+cdata'"&<>test
+<!- -fake comment- ->
+A B C␉D␉␉E F GHI
+-->
+
+<license>
+</license>
+
+<credits>
+</credits>
+
+<meta name="siteURL" content="" />
+<meta name="imageURL" content="" />
+
+<materialList>
+
+</materialList>
+
+<toonMap>
+ <toonDef toonFileId="tf0" index="0" winFileName="toon01.bmp" />
+ <toonDef toonFileId="tf1" index="1" winFileName="toon02.bmp" />
+ <toonDef toonFileId="tf2" index="2" winFileName="toon03.bmp" />
+ <toonDef toonFileId="tf3" index="3" winFileName="toon04.bmp" />
+ <toonDef toonFileId="tf4" index="4" winFileName="toon05.bmp" />
+ <toonDef toonFileId="tf5" index="5" winFileName="toon06.bmp" />
+ <toonDef toonFileId="tf6" index="6" winFileName="toon07.bmp" />
+ <toonDef toonFileId="tf7" index="7" winFileName="toon08.bmp" />
+ <toonDef toonFileId="tf8" index="8" winFileName="toon09.bmp" />
+ <toonDef toonFileId="tf9" index="9" winFileName="toon10.bmp" />
+</toonMap>
+
+<boneList>
+
+<!--
+Bone types:
+[0 : ROTATE : Rotate : 回転 :]
+[1 : ROTMOV : Rotate/Move : 回転/移動 :]
+[2 : IK : IK : IK :]
+[3 : UNKNOWN : Unknown : 不明 :]
+[4 : UNDERIK : Under IK : IK影響下(回転) :]
+[5 : UNDERROT : Under rotate : 回転影響下 :]
+[6 : IKCONNECTED : IK connected : IK接続先 :]
+[7 : HIDDEN : Hidden : 非表示 :]
+[8 : TWIST : Twist : 捩り :]
+[9 : LINKEDROT : Linked Rotate: 回転連動 :]
+-->
+
+</boneList>
+
+<boneGroupList>
+
+</boneGroupList>
+
+<ikChainList>
+
+</ikChainList>
+
+<morphList>
+
+<!--
+Morph types:
+[1 : EYEBROW : まゆ ]
+[2 : EYE : 目 ]
+[3 : LIP : リップ ]
+[4 : EXTRA : その他 ]
+-->
+
+</morphList>
+
+<rigidList>
+
+<!--
+Rigid behavior types:
+[0 : FOLLOWBONE : ボーン追従 ]
+[1 : ONLYDYNAMICS : 物理演算 ]
+[2 : BONEDDYNAMICS : ボーン位置合わせ ]
+-->
+
+</rigidList>
+
+<rigidGroupList>
+
+ <rigidGroup rigidGroupId="rg1" />
+
+ <rigidGroup rigidGroupId="rg2" />
+
+ <rigidGroup rigidGroupId="rg3" />
+
+ <rigidGroup rigidGroupId="rg4" />
+
+ <rigidGroup rigidGroupId="rg5" />
+
+ <rigidGroup rigidGroupId="rg6" />
+
+ <rigidGroup rigidGroupId="rg7" />
+
+ <rigidGroup rigidGroupId="rg8" />
+
+ <rigidGroup rigidGroupId="rg9" />
+
+ <rigidGroup rigidGroupId="rg10" />
+
+ <rigidGroup rigidGroupId="rg11" />
+
+ <rigidGroup rigidGroupId="rg12" />
+
+ <rigidGroup rigidGroupId="rg13" />
+
+ <rigidGroup rigidGroupId="rg14" />
+
+ <rigidGroup rigidGroupId="rg15" />
+
+ <rigidGroup rigidGroupId="rg16" />
+
+</rigidGroupList>
+
+<jointList>
+
+</jointList>
+
+<surfaceGroupList>
+
+</surfaceGroupList>
+
+<vertexList>
+
+</vertexList>
+
+</pmdModel>
+
+<!-- EOF -->
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+ MikuMikuDance
+ model-data(*.pmd) on XML
+-->
+
+
+<pmdModel
+ xmlns="http://mikutoga.sourceforge.jp/xml/ns/pmdxml/101009"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://mikutoga.sourceforge.jp/xml/ns/pmdxml/101009 http://mikutoga.sourceforge.jp/xml/xsd/pmdxml-101009.xsd"
+ schemaVersion="101009"
+
+ name="a A 9 亜'""
+>
+
+
+<description>
+azAZAZ0909あアアゑヵヶΩωЖж<br/>
+┐└漢峠凜熙<br/>
+ヴウ゛ヴパハ゜パ<br/>
+壺壷尭堯<br/>
+\\¥¥<br/>
+髙⑨≒∵¬㈱Σ<br/>
+#$[\]^{|}~<br/>
+<![CDATA[cdata'"&<>test]]><br/>
+<![CDATA[<!--fake comment-->]]><br/>
+A B C	D		E F G
+H
I
+</description>
+
+<license>
+</license>
+
+<credits>
+</credits>
+
+<meta name="siteURL" content="" />
+<meta name="imageURL" content="" />
+
+<materialList>
+
+</materialList>
+
+<toonMap>
+ <toonDef toonFileId="tf0" index="0" winFileName="toon01.bmp" />
+ <toonDef toonFileId="tf1" index="1" winFileName="toon02.bmp" />
+ <toonDef toonFileId="tf2" index="2" winFileName="toon03.bmp" />
+ <toonDef toonFileId="tf3" index="3" winFileName="toon04.bmp" />
+ <toonDef toonFileId="tf4" index="4" winFileName="toon05.bmp" />
+ <toonDef toonFileId="tf5" index="5" winFileName="toon06.bmp" />
+ <toonDef toonFileId="tf6" index="6" winFileName="toon07.bmp" />
+ <toonDef toonFileId="tf7" index="7" winFileName="toon08.bmp" />
+ <toonDef toonFileId="tf8" index="8" winFileName="toon09.bmp" />
+ <toonDef toonFileId="tf9" index="9" winFileName="toon10.bmp" />
+</toonMap>
+
+<boneList>
+
+<!--
+Bone types:
+[0 : ROTATE : Rotate : 回転 :]
+[1 : ROTMOV : Rotate/Move : 回転/移動 :]
+[2 : IK : IK : IK :]
+[3 : UNKNOWN : Unknown : 不明 :]
+[4 : UNDERIK : Under IK : IK影響下(回転) :]
+[5 : UNDERROT : Under rotate : 回転影響下 :]
+[6 : IKCONNECTED : IK connected : IK接続先 :]
+[7 : HIDDEN : Hidden : 非表示 :]
+[8 : TWIST : Twist : 捩り :]
+[9 : LINKEDROT : Linked Rotate: 回転連動 :]
+-->
+
+</boneList>
+
+<boneGroupList>
+
+</boneGroupList>
+
+<ikChainList>
+
+</ikChainList>
+
+<morphList>
+
+<!--
+Morph types:
+[1 : EYEBROW : まゆ ]
+[2 : EYE : 目 ]
+[3 : LIP : リップ ]
+[4 : EXTRA : その他 ]
+-->
+
+</morphList>
+
+<rigidList>
+
+<!--
+Rigid behavior types:
+[0 : FOLLOWBONE : ボーン追従 ]
+[1 : ONLYDYNAMICS : 物理演算 ]
+[2 : BONEDDYNAMICS : ボーン位置合わせ ]
+-->
+
+</rigidList>
+
+<rigidGroupList>
+
+ <rigidGroup rigidGroupId="rg1" />
+
+ <rigidGroup rigidGroupId="rg2" />
+
+ <rigidGroup rigidGroupId="rg3" />
+
+ <rigidGroup rigidGroupId="rg4" />
+
+ <rigidGroup rigidGroupId="rg5" />
+
+ <rigidGroup rigidGroupId="rg6" />
+
+ <rigidGroup rigidGroupId="rg7" />
+
+ <rigidGroup rigidGroupId="rg8" />
+
+ <rigidGroup rigidGroupId="rg9" />
+
+ <rigidGroup rigidGroupId="rg10" />
+
+ <rigidGroup rigidGroupId="rg11" />
+
+ <rigidGroup rigidGroupId="rg12" />
+
+ <rigidGroup rigidGroupId="rg13" />
+
+ <rigidGroup rigidGroupId="rg14" />
+
+ <rigidGroup rigidGroupId="rg15" />
+
+ <rigidGroup rigidGroupId="rg16" />
+
+</rigidGroupList>
+
+<jointList>
+
+</jointList>
+
+<surfaceGroupList>
+
+</surfaceGroupList>
+
+<vertexList>
+
+</vertexList>
+
+</pmdModel>
+
+<!-- EOF -->
--- /dev/null
+最小構成のPMDファイル。
+※ XMLの改行コードはLF。ジェネレータ名は非表示。
+
+名前は空
+説明文は空
+頂点0
+ボーン0
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+ MikuMikuDance
+ model-data(*.pmd) on XML
+-->
+
+
+<!-- -->
+<pmdModel
+ xmlns="http://mikutoga.sourceforge.jp/xml/ns/pmdxml/101009"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://mikutoga.sourceforge.jp/xml/ns/pmdxml/101009 http://mikutoga.sourceforge.jp/xml/xsd/pmdxml-101009.xsd"
+ schemaVersion="101009"
+
+ name=""
+>
+
+
+<description>
+</description>
+
+<license>
+</license>
+
+<credits>
+</credits>
+
+<meta name="siteURL" content="" />
+<meta name="imageURL" content="" />
+
+<materialList>
+
+</materialList>
+
+<toonMap>
+ <toonDef toonFileId="tf0" index="0" winFileName="toon01.bmp" />
+ <toonDef toonFileId="tf1" index="1" winFileName="toon02.bmp" />
+ <toonDef toonFileId="tf2" index="2" winFileName="toon03.bmp" />
+ <toonDef toonFileId="tf3" index="3" winFileName="toon04.bmp" />
+ <toonDef toonFileId="tf4" index="4" winFileName="toon05.bmp" />
+ <toonDef toonFileId="tf5" index="5" winFileName="toon06.bmp" />
+ <toonDef toonFileId="tf6" index="6" winFileName="toon07.bmp" />
+ <toonDef toonFileId="tf7" index="7" winFileName="toon08.bmp" />
+ <toonDef toonFileId="tf8" index="8" winFileName="toon09.bmp" />
+ <toonDef toonFileId="tf9" index="9" winFileName="toon10.bmp" />
+</toonMap>
+
+<boneList>
+
+<!--
+Bone types:
+[0 : ROTATE : Rotate : 回転 :]
+[1 : ROTMOV : Rotate/Move : 回転/移動 :]
+[2 : IK : IK : IK :]
+[3 : UNKNOWN : Unknown : 不明 :]
+[4 : UNDERIK : Under IK : IK影響下(回転) :]
+[5 : UNDERROT : Under rotate : 回転影響下 :]
+[6 : IKCONNECTED : IK connected : IK接続先 :]
+[7 : HIDDEN : Hidden : 非表示 :]
+[8 : TWIST : Twist : 捩り :]
+[9 : LINKEDROT : Linked Rotate: 回転連動 :]
+-->
+
+</boneList>
+
+<boneGroupList>
+
+</boneGroupList>
+
+<ikChainList>
+
+</ikChainList>
+
+<morphList>
+
+<!--
+Morph types:
+[1 : EYEBROW : まゆ ]
+[2 : EYE : 目 ]
+[3 : LIP : リップ ]
+[4 : EXTRA : その他 ]
+-->
+
+</morphList>
+
+<rigidList>
+
+<!--
+Rigid behavior types:
+[0 : FOLLOWBONE : ボーン追従 ]
+[1 : ONLYDYNAMICS : 物理演算 ]
+[2 : BONEDDYNAMICS : ボーン位置合わせ ]
+-->
+
+</rigidList>
+
+<rigidGroupList>
+
+ <rigidGroup rigidGroupId="rg1" />
+
+ <rigidGroup rigidGroupId="rg2" />
+
+ <rigidGroup rigidGroupId="rg3" />
+
+ <rigidGroup rigidGroupId="rg4" />
+
+ <rigidGroup rigidGroupId="rg5" />
+
+ <rigidGroup rigidGroupId="rg6" />
+
+ <rigidGroup rigidGroupId="rg7" />
+
+ <rigidGroup rigidGroupId="rg8" />
+
+ <rigidGroup rigidGroupId="rg9" />
+
+ <rigidGroup rigidGroupId="rg10" />
+
+ <rigidGroup rigidGroupId="rg11" />
+
+ <rigidGroup rigidGroupId="rg12" />
+
+ <rigidGroup rigidGroupId="rg13" />
+
+ <rigidGroup rigidGroupId="rg14" />
+
+ <rigidGroup rigidGroupId="rg15" />
+
+ <rigidGroup rigidGroupId="rg16" />
+
+</rigidGroupList>
+
+<jointList>
+
+</jointList>
+
+<surfaceGroupList>
+
+</surfaceGroupList>
+
+<vertexList>
+
+</vertexList>
+
+</pmdModel>
+
+<!-- EOF -->