Avatar billede appel Novice
04. maj 2003 - 17:55 Der er 16 kommentarer og
1 løsning

En enkel og simpel XML parser i Java

Hvordan laver man en meget simpel XML parser ? Nogen der har nogen korte og "konceptuelle" eksempler ?, således jeg blot kan se tankegangen i det, de skal være langt fra komplette.
Avatar billede arne_v Ekspert
04. maj 2003 - 17:57 #1
J2SE 1.4 og nyere indeholder XML parsere.

Både DOM og SAX.

Skal du bare have eksempler på brug af disse parsere ?
Avatar billede arne_v Ekspert
04. maj 2003 - 17:57 #2
DOM eksempel:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class DomTest {
  private final static String XML_FILE = "C:\\domtest.xml";
  public static void main(String[] args) {
      ArrayList data1 = new ArrayList();
      data1.add("a1");
      data1.add("b2");
      data1.add("c3");
      data1.add("d4");
      writeXml(data1, XML_FILE);
      ArrayList data2 = readXml(XML_FILE);
      System.out.println(data2);
  }
  private static void writeXml(ArrayList data, String filename) {
      try {
        PrintWriter pw = new PrintWriter(new FileOutputStream(filename));
        pw.println("<?xml version='1.0' standalone='yes'?>");
        pw.println("<arraylist>");
        for (int i = 0; i < data.size(); i++) {
            pw.println(
              "  <element>" + (String) data.get(i) + "</element>");
        }
        pw.println("</arraylist>");
        pw.close();
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      }
  }
  private static ArrayList readXml(String filename) {
      ArrayList result = new ArrayList();
      try {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document doc = db.parse(new File(filename));
        NodeList elements = doc.getElementsByTagName("element");
        for (int i = 0; i < elements.getLength(); i++) {
            Node element = elements.item(i);
            result.add(element.getFirstChild().getNodeValue());
        }
      } catch (FactoryConfigurationError e) {
        e.printStackTrace();
      } catch (ParserConfigurationException e) {
        e.printStackTrace();
      } catch (SAXException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      return result;
  }
}
Avatar billede arne_v Ekspert
04. maj 2003 - 17:58 #3
SAX eksempel:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class SaxTest {
  private final static String XML_FILE = "C:\\saxtest.xml";
  public static void main(String[] args) {
      ArrayList data1 = new ArrayList();
      data1.add("a");
      data1.add("bb");
      data1.add("ccc");
      data1.add("dddd");
      writeXml(data1, XML_FILE);
      ArrayList data2 = readXml(XML_FILE);
      System.out.println(data2);
  }
  private static void writeXml(ArrayList data, String filename) {
      try {
        PrintWriter pw = new PrintWriter(new FileOutputStream(filename));
        pw.println("<?xml version='1.0' standalone='yes'?>");
        pw.println("<arraylist>");
        for (int i = 0; i < data.size(); i++) {
            pw.println(
              "  <element>" + (String) data.get(i) + "</element>");
        }
        pw.println("</arraylist>");
        pw.close();
      } catch (FileNotFoundException e) {
        e.printStackTrace();
      }
  }
  private static ArrayList readXml(String filename) {
      ArrayList result = new ArrayList();
      try {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();
        xr.setContentHandler(new MySaxParser(result));
        xr.parse(filename);
      } catch (FactoryConfigurationError e) {
        e.printStackTrace();
      } catch (ParserConfigurationException e) {
        e.printStackTrace();
      } catch (SAXException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      return result;
  }
}

class MySaxParser extends DefaultHandler {
  private StringBuffer element = new StringBuffer();
  private ArrayList result;
  public MySaxParser(ArrayList result) {
      this.result = result;
  }
  public void characters(char buf[], int offset, int len)
      throws SAXException {
      element.append(new String(buf, offset, len));
      return;
  }
  public void startElement(
      String namespaceURI,
      String localName,
      String rawName,
      Attributes atts)
      throws SAXException {
      if (rawName.equals("element")) {
        element = new StringBuffer();
      }
      return;
  }
  public void endElement(
      String namespaceURI,
      String localName,
      String rawName)
      throws SAXException {
      if (rawName.equals("element")) {
        result.add(element.toString());
      }
      return;
  }
}
Avatar billede arne_v Ekspert
04. maj 2003 - 17:59 #4
Det er et ret banalt eksempel med ArrayList<->XML fil.
Avatar billede arne_v Ekspert
10. maj 2003 - 00:21 #5
appel>

Er du kommet videre ?
Avatar billede appel Novice
10. maj 2003 - 12:24 #6
Ja hej og undskyld jeg først svarer nu.

Tak for dit svar, jeg har fundet et ok eksempel på http://www.javaworld.com/javaworld/javatips/jw-javatip128.html

Hvordan er det sammenlignet med dit? Jeg mener din kode ser noget mere ren ud, jeg kan ikke rigtig gennemskue om det er fordi dit kode kan noget mindre eller det bare er fordi det er smartere lavet...
Avatar billede arne_v Ekspert
10. maj 2003 - 12:36 #7
Jeg har ikke kigget på hans kode, men jeg tror følgende citater forklarer:

This tip shows you how to parse XML when running in an applet or other space-restricted environment, such as a J2ME (Java 2 Platform, Micro Edition) application. The process limits functionality in a way that many small applications can accept.

Unfortunately, many Java-based XML parsers are very large; for example, Sun Microsystems' jaxp.jar and parser.jar libraries are 1.4 MB each. If you are running with limited memory (for example, in a J2ME (Java 2 Platform, Micro Edition) environment), or bandwidth is at a premium (for example, in an applet), using those large parsers might not be a viable solution.

The QDParser class occupies around 3 KB after you compile and pack it into a jar file. The source code itself, with comments, is just over 300 lines. This should be small enough for most space-constrained applications, and retain enough of the XML specification to enjoy most of its useful features.

Hans kode er noget simpelt kode beregnet til at køre i "små"
sammenhænge.

Mn kode bruger standard XML libraries.

Enhver der har J2SE 1.4 eller nyere, enhver der har J2SE 1.2 eller
1.3 og har downloadet Crimson eller Xerces kan køre min kode.

Så medmindre du har specielle krav (skal køre på mobil-telefon
eller i applet), så vil jeg helt klart anbefale at gøre det
på standard måden.

Så skal du bare vælge om du vil bruge DOM eller SAX.
Avatar billede appel Novice
10. maj 2003 - 19:40 #8
Hvad er fordele og ulemper ved DOM eller SAX ?
Avatar billede arne_v Ekspert
10. maj 2003 - 19:44 #9
DOM læser hele XML dokumentet op i memory. Fordele: du kan køre
frem og tilbage og hoppe rundt, du kan tilføje og fjerne elementer.
Ulemper: memory forbrug = 2-5 gange XML fil størrelse.

SAX læser XML dokumentet igennem sekventielt. Fordele: hurtigt, bruger
ikke ret meget memeory. Ulemper: det er kun sekventiel adgang til tags,
koden kan godt blive lidt messy.
Avatar billede appel Novice
10. maj 2003 - 21:52 #10
hmmm, jeg tror du har ret mht at det kodeeksempel jeg har fundet er ret specialiseret.
En anden ting: hvordan skal man forstå argumenterne til startelement:
      String namespaceURI,
      String localName,
      String rawName,
      Attributes atts)

Mere konkret, hvordan ville du oprette et Dimension objekt ud fra følgende xml fil ?

<?xml version="1.0"?>
<config>
<dimension y = "50" x="50"/>
</config>
Avatar billede arne_v Ekspert
10. maj 2003 - 21:57 #11
Hvis du er relativt begynder udi XML så:
  ignorer namespaceURL og localName
  rawName = tag navn (altså dimension)
  atts = attributterne (altså x og y)
Avatar billede appel Novice
10. maj 2003 - 21:59 #12
Jeg mangler at tilføje at det skal være ud fra dit SAX eksempel...
Avatar billede appel Novice
10. maj 2003 - 21:59 #13
allkay, jeg er helt newbie mht xml
Avatar billede appel Novice
10. maj 2003 - 22:00 #14
bare ignorer min kommentar 21:59:10
Avatar billede arne_v Ekspert
10. maj 2003 - 22:00 #15
Du kan bruge atts.getValue("x") og atts.getValue("y") til at hente 50
og 50 med.

Namespace er noget man kan bruge til at have forskellige tags
med samme navn bare i forskelligt namespace (ligesom man i Java kan
have flere klasse med samme navn i forskellige packages).
Avatar billede appel Novice
10. maj 2003 - 22:03 #16
cool, det er lige præcis det jeg skal bruge!

Jeg siger mange tak!
Avatar billede arne_v Ekspert
10. maj 2003 - 22:09 #17
Et lidt mere komplekst eksempel med nested tags og attributter:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class SaxTest3 {
    private final static String XML_FILE = "C:\\saxtest.xml";
    public static void main(String[] args) {
        ArrayList data1 = new ArrayList();
        data1.add(new Element(1, "a", true));
        data1.add(new Element(2, "bb", false));
        data1.add(new Element(3, "ccc", true));
        writeXml(data1, XML_FILE);
        ArrayList data2 = readXml(XML_FILE);
        System.out.println(data2);
    }
    private static void writeXml(ArrayList data, String filename) {
        try {
            PrintWriter pw = new PrintWriter(new FileOutputStream(filename));
            pw.println("<?xml version='1.0' standalone='yes'?>");
            pw.println("<arraylist>");
            for (int i = 0; i < data.size(); i++) {
                Element e = (Element)data.get(i);
                pw.println("  <element include='" + e.isInclude() + "'>");
                pw.println("      <nbr>" + e.getNbr() + "</nbr>");
                pw.println("      <name>" + e.getName() + "</name>");
                pw.println("  </element>");
            }
            pw.println("</arraylist>");
            pw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    private static ArrayList readXml(String filename) {
        ArrayList result = new ArrayList();
        try {
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();
            XMLReader xr = sp.getXMLReader();
            xr.setContentHandler(new MySaxParser2(result));
            xr.parse(filename);
        } catch (FactoryConfigurationError e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
}

class MySaxParser2 extends DefaultHandler {
    private StringBuffer element = new StringBuffer();
    private Element elmobj;
    private ArrayList result;
    public MySaxParser2(ArrayList result) {
        this.result = result;
    }
    public void characters(char buf[], int offset, int len)
        throws SAXException {
        element.append(new String(buf, offset, len));
        return;
    }
    public void startElement(
        String namespaceURI,
        String localName,
        String rawName,
        Attributes atts)
        throws SAXException {
        if (rawName.equals("element")) {
            elmobj = new Element();
            elmobj.setInclude(Boolean.valueOf(atts.getValue("include")).booleanValue());
        }
        if (rawName.equals("nbr")) {
            element = new StringBuffer();
        }
        if (rawName.equals("name")) {
            element = new StringBuffer();
        }
        return;
    }
    public void endElement(
        String namespaceURI,
        String localName,
        String rawName)
        throws SAXException {
        if (rawName.equals("element")) {
            result.add(elmobj);
        }
        if (rawName.equals("nbr")) {
            elmobj.setNbr(Integer.parseInt(element.toString()));
        }
        if (rawName.equals("name")) {
            elmobj.setName(element.toString());
        }
        return;
    }
}

class Element {
    private int nbr;
    private String name;
    private boolean include;
    public Element() {
        nbr = 0;
        name = null;
        include = false;
    }
    public Element(int nbr, String name, boolean include) {
        this.nbr = nbr;
        this.name = name;
        this.include = include;
    }
    public int getNbr() {
        return nbr;
    }
    public String getName() {
        return name;
    }
    public boolean isInclude() {
        return include;
    }
    public void setNbr(int nbr) {
        this.nbr = nbr;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setInclude(boolean b) {
        include = b;
    }
    public String toString() {
        return ("[" + nbr + "," + name + "," + include + "]");
    }
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester