XML and its Application

Joe

Thành viên VIP
21/1/13
2,889
1,291
113
Hi

Most of you have more or less confronted XML and somehow worked with XML. But: do you really know What is XML and How to use XML? Please don't scratch your head and murmur "uh...eh..."

XML stands for eXtensible Markup Language. A language? Yes, it's a language. A Programming Language? NO! What's then? XML is a Data Description Language that bases on the plain texts to describe the data formats. (similar to SQL :D) If you so will, XML is comparable to JavaScript Object Notation (JSON). The reason why XML "was invented" was the limitation of HTML (HyperText Markup Language) which is more or less drown under the complexity of the WEB (e.g. big data, image, animation, etc.).

Because of its generality and simplicity XML is easy to learn. The syntactic rules are simple and easily to master. I am NOT going into details here, but simply give you some ideas where XML are to use the best. First of all: some words about the Syntactic Rules.
  • A description of data begins with your own-defined keyword (or tag) which is enclosed by the pair angle brackets ('<' and '>'), then the data (or values) and closed by </tag> (or rarely: <tag/>). Example: <admin>tranhuyvc</admin>. The tag is "admin" and "tranhuyvc" is the "data"
  • Multiple or embedded description of data is possible (i.e. nodes),
  • A tag can possess some parameters, example: <tag parm_1="value_1" parm_2="value_2"></tag>,
  • Parameter-values must be always enclosed by 2 double quotes
  • Comment starts with <!-- and ends with --> (Angle bracket exclamation-mark and 2 dashes and terminated by 2 dashes angle bracket)
  • Specification starts with <? and ends with ?> (Question-Mark and Angle bracket)

As aforementioned XML is useful to describe the
  • data formats
  • access paths
  • data characteristics
for the imports or exports of data between applications and Databases.

However, XML must be "read", then "parsed" before the data could be processed. And it exists only the specifications of World Wide Web Consortium (W3C), but there's no "XML" compiler, nor XML interpreter. The reason is simple: XML tags are user's tags. The definitions and specifications (of tags and functions) are yours. For example: XML of JavaFX is FXML. DOM (Document Object Model) or SAX (Simple API for XML) is only a special application that bases on XML. For JAVA W3C provides a package org.w3c.dom.* which works in sync with the JAVA's package javax.xml.*. How to work with them? You could follow the series posted by quydtkt.

Normally a JAVA developer rarely has to work with numerous and complex XML files so that it would be a joke to include 2 huge DOM (24K) and SAX (21K) packages into an app. But the real joke is that your app must be shipped together with the two mentioned packages. An unwanted dependency from outside. In such a case it's better to develop your "own" XML parser that suits the best to your requirements. I show you here the simplest way to develop a do-it-yourself XML Parser. The main work is the PARSING. Thanks to XML simplicity and generality it's relatively an easy work. However, the work could become more difficult if you start to complicate the XML structure with embedding of nodes. Example:

Simple and easy parsing work:
PHP:
<company>
    <staff id="1">
      ...
    </staff>
      ...
    <staff id="n">
      ...
    <staff>
</company>
or Two-Level nodes
PHP:
<company>
  <department id="R+D">
    <staff id="1">
      ...
    </staff>
      ...
    <staff id="n">
      ...
    <staff>
  </department>
  ...
  <department id="sales">
    <staff id="1">
      ...
    </staff>
      ...
    <staff id="n">
      ...
    <staff>
  </department>
</company>
Complex XML with embedding nodes: node "<cacao>" is embedded within node "<Chocolate id="R">"
PHP:
<company>
    <Chocolate id="R">
      <price>1 Euro</price>
      <cacao>
        <dark>80</dark>
        <brown>50</brown>
        <light>30</light>
      </cacao>
      <form>round</form>
    </Chocolate>
      ...
  </company>
The API is named XMLEngine. A 514 Java-coding lines (incl. comments and JAVA-Styled Method desciption). You can download the sources from HERE. The parsing of Node-Embedding structure is intensive and complex and I don't intend to replace the DOM/SAX package of W3C. Meaning: if you have to work with complex XML structures you should go with W3C DOM&SAX package. For a simple XML structure ("un-embedded" nodes) it's much better to develop your own XML parser. An independence from the others (license, fee, bugs, maintenance, etc.)

Note: Level always starts with 0 (as root).

Constructor:
  • public XMLEngine(String fileName) throws Exception

Methods:
  • public void deleteTag(String node, String tag, int x): delete a tag at node at level x
  • public void addTag(String node, String tag, String val, int x): add a tag with value to node at level x
  • public void renameTag(String node, String oTag, String nTag, int x): rename tag oTag to nTag of node at level x
  • public void modifyValue(String node, String tag, String val, int x): modify the value of a tag at node of level x with val
  • public void deleteNode(String node, int x) throws Exception: delete node at level x
  • public void modifyNode(String node, int x) throws Exception: modify the content (tags, values) of node at level x
  • public void insertNode(String node, int x, int p) throws Exception: insert or add node (with content: tags, values) at level x. p < 0: add, p >= 0 insert at this position.
  • public List<String> getSpecs(): retrieve the header specifications
  • public String getRoot(): retrieve the root name
  • public List<String> getRootNodes() throws Exception: list all root nodes
  • public List<String> getNodes(int x) throws Exception: list all nodes at level x
  • public List<String> getTags(String node): list all tags of root node
  • public List<String> getTags(String node, int x): list all tags of node at level x
  • public List<String> getData(String node): list all values (of tags) of root node
  • public List<String> getData(String node, int x): list all values (of tags) of node at level x
  • public int getLevelCount(): return the number of level
  • public int getNodeCount(int x) throws Exception: return the number of nodes at level x (0:for root)
  • public void saveAs(String fName) throws Exception: save the XMLEngine content as XML file.

Example:
PHP:
public class Test {
  public static void main(String argv[]) throws Exception {
    XMLEngine xml = new XMLEngine(argv.length > 0? argv[0]:"file.xml");
    System.out.println("----------Append Node 4------------");
    xml.insertNode("joe.xml", 0, -1); //<--from an external file
    List<String> nodes = xml.getNodes(0);
    for (String s:nodes) System.out.println("Node:"+s);
    System.out.println("----------------------------------");
    for (String N : nodes) {
      List<String> atts = xml.getTags(N);
      List<String> els = xml.getData(N);
      System.out.println("\nnode:"+N);
      for (int i = 0, mx = els.size(); i < mx; ++i)
        System.out.println(atts.get(i)+":"+els.get(i));
    }
    xml.saveAs("out.xml"); // save to out.xml
  }
}
file joe.xml. The file.xml (click HERE)
PHP:
    <staff id="4">
       <firstname>JOE</firstname>
       <lastname>Nartca</lastname>
       <nickname>Joca</nickname>
       <salary>100000</salary>
       <age>45</age>
     </staff>
the output:
Code:
C:\JoeApp\DOM>javac -g:none -d ./classes XMLEngine.java

C:\JoeApp\DOM>java Test
----------Append Node 4------------
Node:staff id="1"
Node:staff id="2"
Node:staff id="3"
Node:staff id="4"
----------------------------------

node:staff id="1"
id:"1"
firstname:yong
lastname:mook kim
nickname:mkyong
salary:2000000
age:29

node:staff id="2"
id:"2"
firstname:low
lastname:yin fong
nickname:fong fong
salary:1000000

node:staff id="3"
id:"3"
firstname:Ali
lastname:Baba
nickname:Alibaba
salary:199000
age:40

node:staff id="4"
id:"4"
firstname:JOE
lastname:Nartca
nickname:Joca
salary:100000
age:45

C:\JoeApp\DOM>
and the created file out.xml
PHP:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<company>
  <staff id="1">
    <firstname>yong</firstname>
    <lastname>mook kim</lastname>
    <nickname>mkyong</nickname>
    <salary>2000000</salary>
    <age>29</age>
  </staff>
  <staff id="2">
    <firstname>low</firstname>
    <lastname>yin fong</lastname>
    <nickname>fong fong</nickname>
    <salary>1000000</salary>
  </staff>
  <staff id="3">
    <firstname>Ali</firstname>
    <lastname>Baba</lastname>
    <nickname>Alibaba</nickname>
    <salary>199000</salary>
    <age>40</age>
  </staff>
  <staff id="4">
    <firstname>JOE</firstname>
    <lastname>Nartca</lastname>
    <nickname>Joca</nickname>
    <salary>100000</salary>
    <age>45</age>
  </staff>
</company>
Enjoy...:)
or
Suffer...:((

(will continue)
 

Attachments

Sửa lần cuối:

Joe

Thành viên VIP
21/1/13
2,889
1,291
113
(cont.)

XML is a Data Description Language. In the past developers had to "invent" kinda algorithm for their Data Description purpose. I show you how to "internationalize" your app with XML. As said, XML is useful to import or to export all kinds of data between applications and Databases. JAVA usually uses the API Properties to "import" data from a file in a special format (which originates from UNIX). Example:

A typical Properties file (e.g. config.txt)
Code:
#----------------------------------------------
# ServerConfig
#------------------------------------------------
Host=localhost
Port=30751
#------------------------------------------------
and the processing part in Java:
PHP:
   try {
     Properties prop = new Properties();
     prop.load(new FileInputStream("config.txt"));
     String host = prop.getProperty("Host"); // <<--localhost
     int port = Integer.parseInt(prop.getProperty("Port")); // <<--30751
     ...
  } catch (Exception e) {
    e.printStackTrace();
  }
The problems with JAVA Properties is the flat structure: one key for one value. If you want to "internationalize" your app with Java Properties you have to create N properties files for N languages. Example:
  • English: english.txt
  • German: german.txt
  • French: french.txt
  • Vietnamese: vietnamese.txt
the file english.txt
Code:
label_1=This is English
button=Click HERE
combo=English,German,French,Vietnamese
label_2=Please Select
similar to that for german.txt, french.txt and vietnamese.txt. Problem is that you have to renew your "language properties" each time when the user wish to switch, for example, from English to German. With XML you don't have to "renew" the properties, but you need only to switch the "node" according to the wish of the user. Example:

the XML file I18N.xml
PHP:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<language>
  <english>
    <label_1>This is English</label_1>
    <button>Click HERE</button>
    <combo>English,German,French,Vietnamese</combo>
    <label_2>Please Select</label_2>
  </english>
  <german>
    <label_1>Dies ist Deutsch</label_1>
    <button>Klick HIER</button>
    <combo>Englisch,Deutsch,Franzoesisch,Vietnamesisch</combo>
    <label_2>Bitte auswaehlen</label_2>
  </german>
  <french>
    <label_1>C'est francais</label_1>
    <button>Cliquez ici</button>
    <combo>anglais,allemand,francais,vietnamien</combo>
    <label_2>Veuillez selectionner</label_2>
  </french>
  <vietnamese>
    <label_1>Day la tieng Viet</label_1>
    <button>Bam vao day</button>
    <combo>Anh,Duc,Phap,Viet</combo>
    <label_2>Vui long chon</label_2>
  </vietnamese>
</language>
and the "switch" could be as following:
PHP:
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
// Joe Nartca (C)
// I(nternationalizatio)N or I18N
public class I18N extends JFrame implements ActionListener {
  public I18N(String xmlFile) throws Exception {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // start XMLEngine
    xml = new XMLEngine(xmlFile);
    List<String> nodes = xml.getRootNodes();
    data = xml.getData("english");
    //
    setLayout(null);
    lab_1 = new JLabel();
    lab_1.setBounds(80, 10, 100, 25);
    but   = new JButton();
    but.setBounds(70, 40, 100, 25);
    lab_2 = new JLabel();
    lab_2.setBounds(20, 70, 150, 25);
    combo = new JComboBox< >( );
    combo.setBounds(20, 90, 200, 25);
    add(lab_1);
    add(but);
    add(lab_2);
    add(combo);
    loadLanguage();
    setSize(300, 200);
    setVisible(true);
  }
  // user switches the language via ComboBox
  public void actionPerformed(ActionEvent ev) {
    int idx = combo.getSelectedIndex();
    switch (idx) {
    case 0: data = xml.getData("english");
            break;
    case 1: data = xml.getData("german");
            break;
    case 2: data = xml.getData("french");
            break;
    default: data = xml.getData("vietnamese");
    }
    loadLanguage();
  }
  //
  private void loadLanguage() {
    lab_1.setText(data.get(0));
    but.setText(data.get(1));
    lab_2.setText(data.get(3));
    combo.removeActionListener(this);
    combo.removeAllItems();
    String[] items = data.get(2).split(",");
    for (String s:items) combo.addItem(s);
    combo.addActionListener(this);
  }
  //
  private List<String> tags, data;
  private JComboBox<String> combo;
  private JLabel lab_1, lab_2;
  private JButton but;
  //
  private XMLEngine xml;
  //
  public static void main(String... a) throws Exception {
    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
    I18N i18N = new I18N(a.length > 0?a[0]:"i18n.xml");
  }
}
and here is the result:

lang.png

For your comparison: I18N_P.java using JAVA Properties + 4 diff.files: English.txt, german.txt, french.txt and vietnamese.txt
PHP:
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
// Joe Nartca (C)
// I(nternationalizatio)N or I18N
public class I18N_P extends JFrame implements ActionListener {
  public I18N_P(String propFile) throws Exception {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLayout(null);
    lab_1 = new JLabel();
    lab_1.setBounds(80, 10, 100, 25);
    but   = new JButton();
    but.setBounds(70, 40, 100, 25);
    lab_2 = new JLabel();
    lab_2.setBounds(20, 70, 150, 25);
    combo = new JComboBox< >( );
    combo.setBounds(20, 90, 200, 25);
    add(lab_1);
    add(but);
    add(lab_2);
    add(combo);
    loadLanguage(propFile);
    setSize(300, 200);
    setVisible(true);
  }
  public void actionPerformed(ActionEvent ev) {
    String propFile = null;
    int idx = combo.getSelectedIndex();
    switch (idx) {
    case 0: propFile = "english.txt";
            break;
    case 1: propFile = "german.txt";
            break;
    case 2: propFile = "french.txt";
            break;
    default: propFile = "vietnamese.txt";
    }
    loadLanguage(propFile);
  }
  //
  private void loadLanguage(String propFile) {
    try { // renew the properties
      Properties prop = new Properties();
      prop.load(new FileInputStream(propFile));
      lab_1.setText(prop.getProperty("label_1"));
      but.setText(prop.getProperty("button"));
      lab_2.setText(prop.getProperty("label_2"));
      combo.removeActionListener(this);
      combo.removeAllItems();
      String[] items = prop.getProperty("combo").split(",");
      for (String s:items) combo.addItem(s);
      combo.addActionListener(this);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
  //
  private JComboBox<String> combo;
  private JLabel lab_1, lab_2;
  private Properties prop;
  private JButton but;
  //
  private XMLEngine xml;
  //
  public static void main(String... a) throws Exception {
    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
    I18N_P i18N = new I18N_P(a.length > 0?a[0]:"english.txt");
  }
}
Joe
 
Sửa lần cuối: