iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 8
0
Software Development

做一個JVM語言系列 第 8

Antlr練習,轉換JSON到XML

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));
}
}

主程式標準的寫法,大概都是這樣。


上一篇
Antlr練習,解析CSV檔
下一篇
Antlr練習,生成函數呼叫圖(Call Graph)
系列文
做一個JVM語言12
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言