XML及其相關的應用,曾經是很多人的回憶(痛?),
最近還被SOAP資料交換(XML)整到,
尤其是WSDL有些很舊的版本,沒辦法自動產生JAVA代碼。
因為XML太艱深,所以另一個極端(簡單)的網路資料交換的格式(JSON)就興起,
且行之有年。雖然開放數據(OPEN DATA),還是很多政府機關喜歡用EXCEL, 文字檔,
CSV檔來資料交換,但是XML的應用逐漸變少。
本練習是轉換JSON到XML。
JSON示例:
{
    "description" : "An imaginary server config file",
    "logs" : {"level":"verbose", "dir":"/var/log"},
    "host" : "antlr.org",
    "admin": ["parrt", "tombu"],
    "aliases": []
}
轉換成XML示例:
<description>An imaginary server config file</description>
<logs>
<level>verbose</level>
<dir>/var/log</dir>
</logs>
<host>antlr.org</host>
<admin>
<element>parrt</element>
<element>tombu</element>
</admin>
<aliases></aliases>
有了之前的經驗,做程式碼轉換的工作,Antlr的預設LISTNER模式,就很好用。
先抄一下別人寫的JSON文法檔
// Derived from http://json.org
grammar JSON;
json:   object
    |   array
    ;
object
    :   '{' pair (',' pair)* '}'    # AnObject
    |   '{' '}'                     # EmptyObject
    ;
	
array
    :   '[' value (',' value)* ']'  # ArrayOfValues
    |   '[' ']'                     # EmptyArray
    ;
pair:   STRING ':' value ;
value
    :   STRING		# String
    |   NUMBER		# Atom
    |   object  	# ObjectValue
    |   array  		# ArrayValue
    |   'true'		# Atom
    |   'false'		# Atom
    |   'null'		# Atom
    ;
LCURLY : '{' ;
LBRACK : '[' ;
STRING :  '"' (ESC | ~["\\])* '"' ;
fragment ESC :   '\\' (["\\/bfnrt] | UNICODE) ;
fragment UNICODE : 'u' HEX HEX HEX HEX ;
fragment HEX : [0-9a-fA-F] ;
NUMBER
    :   '-'? INT '.' INT EXP?   // 1.35, 1.35E-9, 0.3, -4.5
    |   '-'? INT EXP            // 1e10 -3e4
    |   '-'? INT                // -3, 45
    ;
fragment INT :   '0' | '1'..'9' '0'..'9'* ; // no leading zeros
fragment EXP :   [Ee] [+\-]? INT ; // \- since - means "range" inside [...]
WS  :   [ \t\n\r]+ -> skip ;
其中 ,
'-'? :要嘛不出現,最多只能出現一次。
fragment : 文法中有很多重覆出現的元素時,可以給他一個簡單一點的別名,如文法裏的INT,它在NUMBER文法裏出現多次,就用INT代替,然後在下面的fragment INT :,把其內容詳述一次。
而# 是LABEL的註記,不是註解,註解是// ,不要搞混了。
本來,設計(E)BNF文法是一個高難度的工作,因為前人的無私分享,很多時候拿來用即可。
public class JSON2XML {
    public static class XMLEmitter extends JSONBaseListener {
....................................................
public static void main(String[] args) throws Exception {
    String inputFile = null;
    if ( args.length>0 ) inputFile = args[0];
    InputStream is = System.in;
    if ( inputFile!=null ) {
        is = new FileInputStream(inputFile);
    }
    ANTLRInputStream input = new ANTLRInputStream(is);
    JSONLexer lexer = new JSONLexer(input);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    JSONParser parser = new JSONParser(tokens);
    parser.setBuildParseTree(true);
    ParseTree tree = parser.json();
    // show tree in text form
//        System.out.println(tree.toStringTree(parser));
    ParseTreeWalker walker = new ParseTreeWalker();
    XMLEmitter converter = new XMLEmitter();
    walker.walk(converter, tree);
    System.out.println(converter.getXML(tree));
}
}
主程式標準的寫法,大概都是這樣。