Avatar billede tobiashm Nybegynder
18. juni 2003 - 17:06 Der er 19 kommentarer og
1 løsning

xml parsing og reference til variable

Jeg har midlertidigt glemt hvordan man programmere i Java :-)

Hvis jeg har lavet en extension af DefaultHandler til at (SAX) parse en xml fil, og i løbet af parsningen gerne vil have opdateret et object fra den klasse der har kaldt parseren - hvordan er det så man gør?

Altså, hvis jeg vil lave noget ala:

String toupdate = "";
handler = new MyHandler(toupdate);
xmlreader.setContentHandler(handler);
xmlreader.parse(xmlfile);
// toupdate er nu blevet ændret...
Avatar billede tazly Nybegynder
18. juni 2003 - 17:23 #1
// Prøv med en MyHandler klasse a' la det her:

public class MyHandler extends ContentHandler{
    private Object toUpdate;
    MyHandler(Object toUpdate){
        this.toUpdate = toUpdate;
    }
    // her er der mange mulighder. Fx:
    public void startDocument(){
        toUpdate = "updated";
    }
}

// Kør så din kode:
...
ContentHandler handler = new MyHandler(toUpdate);
...
Avatar billede tobiashm Nybegynder
18. juni 2003 - 17:25 #2
Ja, det er jo det der desvære ikke lige virker :-(
Avatar billede tazly Nybegynder
18. juni 2003 - 17:26 #3
// Lige et par rettelser. En klasse kan naturligvis ikke extende et interface.

public class MyHandler extends DefaultHandler{
    private Object toUpdate;
    MyHandler(Object toUpdate){
        this.toUpdate = toUpdate;
    }
    // her er der mange mulighder. Fx:
    public void startDocument(){
        toUpdate = "updated";
        // et kald til super er nok på sin plads her.
        super.startDocument();
    }
}

// Kør så din kode:
...
ContentHandler handler = new MyHandler(toUpdate);
...
Avatar billede tazly Nybegynder
18. juni 2003 - 17:27 #4
Kan du se om din startDocument() bliver kaldt? Prøv at indsætte en debug statement i den. Fx System.out.println("startDocument() called");
Avatar billede arne_v Ekspert
18. juni 2003 - 17:48 #5
Det virker ikke fordi i constructoren sætter du en referance i klassen
til at pege på argumentet.

Senere sætter du så den referance til at pege på noget andet.

Men det ændrer jo ikke på argumentet.

To muligheder:

1)  send objektet over som ovenfor og behold argumentet men
    ændre det (f.eks. med en set metode)

2)  som variant af #1 send end et container objekt over og
    put output objekt i det
Avatar billede arne_v Ekspert
18. juni 2003 - 17:49 #6
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
18. juni 2003 - 17:50 #7
Der bliver sendt en ArrayList over som argument, men den bliver ikke
forsøgt erstattet med en anden med:
  result=
men der bliver tilføjet data til den med:
  result.add
Avatar billede tobiashm Nybegynder
18. juni 2003 - 18:16 #8
arne_v> Er dit eksempel noget nu har kørt?
Jeg har allerede en hashtabel som bliver sendt over, og som heller ikke bliver opdateret. Og den bliver jo også kun modificeret med .put()
Avatar billede tobiashm Nybegynder
18. juni 2003 - 18:23 #9
public class UpdateHandler extends DefaultHandler {
  private Hashtable hash;
  public UpdateHandler(Hashtable hash) {
    this.hash = hash;
  }
  public void startElement(...) {
    ...
    hash.put(key, value);
    ...
  }
}
Avatar billede arne_v Ekspert
18. juni 2003 - 18:25 #10
Ja - ovenstående kode kører.

Output:

[a, bb, ccc, dddd]

(som ser korrekt ud)
Avatar billede arne_v Ekspert
18. juni 2003 - 18:27 #11
Jeg tog udgangspunkt i den oprindelige kode i spørgsmålet og
tazlys kode.

Og et String objekt kan ikke ændres.
Avatar billede arne_v Ekspert
18. juni 2003 - 18:28 #12
Koden i din 18:23:46 kommentar ser meget OK ud.
Avatar billede arne_v Ekspert
18. juni 2003 - 18:29 #13
Hvilket er en anden måde at sige: vi skal nok se noget mere kode
og have lidt mere info om hvordan den ikke virker for at kunne
komme videre.
Avatar billede tobiashm Nybegynder
18. juni 2003 - 21:14 #14
Ok

public class mainview extends JApplet {
  public static final String = "/getUpdateNodes?";
  private Hashtable nodeHash;

  public void init() {
    nodeHash = new Hashtable();
    ...
    nodeHash.put(rootId, rootNode);
  }

  public void start() {
    XMLReader xmlreader;
    try {
      SAXParserFactory spf = SAXParserFactory.newInstance();
      SAXParser sp = spf.newSAXParser();
      xmlreader = sp.getXMLReader();

      String updateNodes = "Root";
      while (updateNodes != "") {
        System.out.println(updateNodes);
        URL url = new URL("http", "localhost", UPDATE_URL + updateNodes);
        updateCSIDs = "";
        UpdateHandler handler = new UpdateHandler(nodeHash, updateCSIDs);
        xmlreader.setContentHandler(handler);
        xmlreader.parse(new InputSource(url.openStream()));
        System.out.println(nodeHash);
      }
    } catch (IOException e) {
      e.printStackTrace();
    } catch (ParserConfigurationException e) {
      e.printStackTrace();
    } catch (SAXException e) {
      e.printStackTrace();
    }
  }
}
Avatar billede arne_v Ekspert
18. juni 2003 - 21:41 #15
Jeg prøvede lige at lave mit lille eksempel om til at bruge Hashtable:

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

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);
      Hashtable 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 Hashtable readXml(String filename) {
      Hashtable result = new Hashtable();
      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 Hashtable result;
  private int n;
  public MySaxParser(Hashtable result) {
      this.result = result;
      n = 0;
  }
  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")) {
        n++;
        result.put(Integer.toString(n), element.toString());
      }
      return;
  }
}

og det virker fint - output er:

{4=dddd, 3=ccc, 2=bb, 1=a}

så jeg er stadig på bar bund.
Avatar billede tobiashm Nybegynder
18. juni 2003 - 22:39 #16
Det sku da mystisk - også fordi hashtabellen indeholder en node i et JTree, som bliver hentet ud under parsningen og får tilføjet childnodes - og det går fint. Men når de samme nye nodes tilføjes til hashtabellen, går det ikke.

Ellers er den største forskel mellem dit og mit program, at mit er en applet - men det burde ikke betyde så meget...?
Avatar billede arne_v Ekspert
18. juni 2003 - 22:41 #17
Du har checket for exceptions i applet console under kørsel ?
Avatar billede tobiashm Nybegynder
18. juni 2003 - 22:55 #18
Og den ændre faktisk også noget (navnet ved .toString()) på root noden. Så referencen til det objekt som er i hashtabelen kommer med, men men ikke referencen til selve tabelen.
Avatar billede tobiashm Nybegynder
18. juni 2003 - 23:17 #19
damn damn damn!
Det er bare en lille f*#¤$@% fejl fra min side - et stykke af koden som var skrevet forkert! :-(
Men nu virker det!
Sådan er det nogen gange - så kan man ikke se skoven :-/

(Lavede en simpel handler klasse, som kun tilføjede et ellement til hashtabellen, og da det virkede, måtte jeg kigge den anden igennem endnu en gang - og så pludselig var den der.)
Avatar billede arne_v Ekspert
19. juni 2003 - 06:48 #20
Jeg kender fornemmelsen.

:-)
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