# xml schreiben und parsen in java



## AleX (13. Januar 2003)

hi,
wollte fragen ob hier jemand schon mal was mit java in verbindung mit xml gemacht hat??? (xml als lokale datenablage)

Nun mein prob:
Ich bräuchte unbedingt ein einfaches Beispiel, in dem eine xml datei aus java aus geschrieben wird und danach wieder eingelsen, und zwar so dass man auf bestimmte werte zugreifen kann.

Hab das schon gemacht, als document objekt model DOM und mit dem SAX hab ich es mir auch angesehen, aber ich schaff es einfach nicht, die xml korrekt als DOM einzulesen und dann per Xpath(oder anders, falls es noch eine andere möglichkeit gibt) auf bestimmte werte zuzugreifen...

Wenn sich jemand opfern würde und eine kleines prog mit funktionierendem schreiben und einlesen posten würde, dann *freu*.

 please, ist wirklich wichtig und ich komm einfach nicht weiter


----------



## Christian Fein (13. Januar 2003)

Es gibt 3 möglichkeiten

DOM, SAX, JDOM

DOM liest das ganze XML Document in einen Baum ein und mann kann über die verschiedene Elemente navigieren.
Das ist recht Tricky denn auch ein einzelner Whitespace im Document kann (DTD abhängig) eine Textnode sein.

SAX durchläuft das Dokument und reagiert auf Nodes durch bestimmte Handler. Sehr schnell und gut beim lesen.

JDOM ist OpenSource von der ApacheGroup (Qualität!) und ist dabei demnächst in den Java Standard mit aufgenommen zu werden. Ist mittlerweile defacto Standard. Und auch mein Favorit weil es:
a) JavaTypischer 
b) Unkomplizierter
ist.

Also einlesen mit SAXBuilder
path der komplette pfad zur XML Datei

```
import org.jdom.*;
import org.input.SAXBuilder;
import org.jdom.output.XMLOutputter;
..
..
SAXBuilder sxbuild 
     = new SAXBuilder();
InputSourc is 
     = new InputSource(path);
Document doc = sxbuild.build(is);
Element root = doc.getRootElement();
```

nun hast du ein Dokument eingeselen wenn du ein Document erstellen willst geht das so:


```
Element root = new   
    Element("StartElement");
Document doc = new Document(root);
```

Dann kannst du neue Elemente anhängen

```
root.appendChild(new Element("kindElement"));
```
usw

Ausgegeben wird das ganze dann mit
org.jdom.output.XMLOutputter
der die Zeichenfolge fürs Einrücken und 
denn boolean wert ob neue Elemente in neue Zeilen gesetzt werden.

Zudem brauchen wir noch einen FileOutputStream welche für die reine Dateioperation zuständig ist. Dieser wird an den Outputter noch mit dem Document zusammen zum Ausgeben übergeben.



```
XMLOutputter outputter 
  = new XMLOutputter(" ",true);
FileStream output
    = new FileOutPutStream("file.xml");
outputter.output(doc,output);
```

Damit wurde das File erstellt

hoffe das hilft


----------



## AleX (13. Januar 2003)

jo big thx! 

hat mir sehr weitergeholfen, ich hatte nur noch ein kleines prob mit der logik bzw. Verständnis.

Hab es jetzt folgendermaßen mit DOM gelöst: (schreiben) 
Allerdings bin ich mir nicht sicher, ob das alles so professionel gelöst ist, also falls was mieses drin ist, bitte sagen.



import java.io.*;
import org.w3c.dom.*;
import com.sun.xml.tree.XmlDocument;

public class XmlWriter
{
    public static void main(String[] args)
    {
        XmlWriter writer = new XmlWriter();
        XmlDocument doc = writer.createFile();
        try
        {
            writer.writeFile(doc, args[0]);
        }
        catch (IOException e)
        {
            System.err.println("Fehler beim Schreiben: ");
            System.err.println(e);
        }
    }

    public XmlDocument createFile()
    {
        XmlDocument doc = new XmlDocument();

        Text text = doc.createTextNode("viel Text");

        Element child2 = doc.createElement("Child2");
        child2.appendChild(text.cloneNode(false));

        Element child1 = doc.createElement("Child1");
        child1.appendChild(text.cloneNode(false));
        child1.appendChild(child2);

        Element durchlauf = doc.createElement("Durchlauf");
        Attr nr = doc.createAttribute("Nummer");
        durchlauf.setAttributeNode(nr);

        Element root = doc.createElement("Teil");
        root.setAttribute("root", "true"); 
        for (int i = 0; i <= 1; i++)
        {
            nr.setValue((new Integer(i)).toString());
            root.appendChild(durchlauf.cloneNode(false));
            root.appendChild(child1.cloneNode(true));
        }

        Comment kommentar = doc.createComment("Kommentar");
        doc.appendChild(kommentar);
        doc.appendChild(root);

        return doc;
    }

    public void writeFile(XmlDocument doc, String file)
    throws IOException
    {
        FileOutputStream out = new FileOutputStream(file);        
        doc.write(out);
        out.close();
    }
}


Jetzt nur noch eine Frage: Einlesen mit SAX - kein prob wenn ichs bloss wiedergeben möchte, aber wenn ich auf bestimmte werte zugreifen will, da ich praktisch eine applikation schreibe, wo die einstellungen in xml gespeichert werden, geht das doch mit xpath?! oder?

Auf jedenfalls schon mal ein fettes lob von mir, für die mühe!


----------



## Christian Fein (13. Januar 2003)

Ich seh nichts unprofessionelles an deinem 
Code.

DOM ist die Standardimplementierung vom w3c und sich daran zu halten ist immer gut 

Nun aber eine änderrung würde ich schon nehmen. Und zwar den XMLOutputter dieser ist ein wunderbares mittel XML Dokumente gleich mit angenehmen Whitespaces darzustellen.

Nun du greifst auf Werte in JDOM 
Element elem = root.getChild("MyElement");
String myValue = elem.getText();

Mit DOM geht das wenn ich mich recht errinnere:
Durchlaufe die Children:

```
NodeList childs = root.getChildNodes();
for(int x = 0;x < childs.getLengt();x++)
{
 Node tmp = childs.item(x);
  if((tmp.getNodeType()==Node.TEXT_NODE)     
  &&(tmp.getNodeName.equals("gesucht"))  
  {
    String myValue = tmp.getNodeValue();
  }   
       
}
```

Also mann sieht durch dir relativ Komplizierte DOM implementierung fährst du bei abfrage von werten mit JDOM besser. Weil JDOM Text nicht als Textnode behandelt wie in DOM sondern dich über die Methode getText() eines JDOM elements an dessen inhalt ranlässt


----------



## AleX (13. Januar 2003)

nochmal danke.

werd das jetzt mal mit dem JDOM machen.  

Denn ich bin schon auch deiner Meinung, dass es doch etwas kompliziert bzw. einfach umständlich mit DOM ist, insbesondere beim Einlesen.


----------



## AleX (15. Januar 2003)

ok, ich glaub jetzt habe ich alle deine anweisungen befolgt 

So sieht das ganze jetzt mit JDOM aus:


```
import org.jdom.Element;
import org.jdom.Document;
import org.jdom.output.XMLOutputter;

import java.io.IOException;
import java.io.FileOutputStream;

public class writer {
    public static void writer_start(String filename, String[] elementName, String[] content) {
        writer writer = new writer();
        Document doc = writer.createFile(filename, elementName, content);
        try {
            writer.writeFile(doc, filename);
        } catch (IOException e) {
            System.err.println("Fehler beim Schreiben: " + e);
        }//catch
    }//main

    public Document createFile(String filename, String[] elementName, String[] content) {

        Document doc = new Document();
        Element rootElement = new Element("root");
        doc.setRootElement(rootElement);


        // -----------> XML-Aufbau
        for (int i = 0; i < elementName.length || i < content.length; i++) {
            Element element = new Element(elementName[i]);
            element.addContent(content[i]);
            rootElement.addContent(element);
        }
        // -----------> XML-Aufbau end


        // -----------> XML-Einlesen test
        try{
        Element el = rootElement.getChild("one");
        String tagValue = el.getText();
        System.out.println(tagValue);
        }catch (Exception e){
            System.err.println("Fehler beim Einlesen: xml-tag nicht gefunden");
        }
        // -----------> XML-Einlesen test end


        return doc;
    }//createFile

    public void writeFile(Document doc, String filename) throws IOException {
        XMLOutputter outputter = new XMLOutputter(" ", true);
        FileOutputStream output = new FileOutputStream(filename);
        outputter.output(doc, output);

    }//writeFile
}//writer
```


----------



## Christian Fein (15. Januar 2003)

Jo sieht ok aus =)


----------



## AleX (16. Januar 2003)

*probs gehen weiter... *

jetzt meld ich mich doch noch mal...

Also folgendes prob: Ziehe mir von einem server ein xml file, welches ich daraufhin einem TableModel übergeben möchte...

Nur jetzt sieht die formatierung der xml so aus:

```
<?xml version="1.0" encoding="ISO-8859-1" ?> 
- <products>
- <customer id="0027">
- <product unid="3B6A03E551ABF630C1256C7D00288448">
  <item name="ProductManufacturer" value="Liebherr" /> 
  <item name="ArticleCategory" value="Kräne" /> 
  <item name="ProductModel" value="LT 10-45 S" /> 
  </product>
- <product unid="410E1C3F452C117DC1256C7D0028D350">
  <item name="ProductManufacturer" value="Sonstige Hersteller" /> 
  <item name="ArticleCategory" value="Kräne" /> 
  <item name="ProductModel" value="S 15" /> 
  </product>
usw...
```

und ich brings einfach nicht fertig, z.B. von customer mit der id 0025 die value Liebherr aus ProductManufacturer auszulesen...
(mit JDOM)

Ansonsten sollte es ja dann kein problem sein, die sachen in einen array bzw object zu legen, die wiederrum in einen vektor und das dann einem tablemodel zu übergeben... <- wenn ich mich irre bitte sagen


----------



## Christian Fein (17. Januar 2003)

doc ist geparste XMLDocument

Element products doc.getRootElement();
Element costumer = products.getChild("customer");
String id = costumer.getAttribute("id");

sorry falls du etwas nachbessern musst. ich habe das aus dem gedächtnis geschrieben aber die api-dokumentation hast du ja um eventuelle Fehler herauszubekommen


----------



## AleX (18. Januar 2003)

jo thx, habs hinbekommen =)


----------



## shocking (3. Mai 2007)

Hi,

ich habe mich an demselben Thema versucht, scheitere aber offensichtlich.
Ich habe das ganze direkt in ein Servlet gepackt und möchte ankommende Daten in pdf umwandeln. Hier mein Code:

```
public class pdfServlet extends HttpServlet {
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

        try{
            response.setContentType("application/pdf");
            
            Document doc = new Document(new Element("root"));
            Element rootElement = doc.getRootElement();
        
            String[] elements = {"Eins", "Zwei"};
            String[] content = {"eins", "zwei"};
            
            for (int i = 0; i < elements.length; i++) {
                Element element = new Element(elements[i]);
                element.addContent(content[i]);
                rootElement.addContent(element);
            }
            
            XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
            FileOutputStream output = new FileOutputStream("offer.xml");
            outputter.output(doc, output);          
                        
            //Setup a buffer to obtain the content length
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            
            //Setup FOP
            FopFactory fopFactory = FopFactory.newInstance();
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);

            //Setup Transformer
            
            String fnXsl = getServletContext().getRealPath("/pdfStylesheet.xsl");
            Source xsltSrc = new StreamSource(new File(fnXsl));
            TransformerFactory tFactory = TransformerFactory.newInstance();
            Transformer transformer = tFactory.newTransformer(xsltSrc);

            //Make sure the XSL transformation's result is piped through to FOP
            Result res = new SAXResult(fop.getDefaultHandler());

            //Setup input
            Reader reader = new StringReader(doc.toString());
            StreamSource src = new StreamSource(reader);

            //Start the transformation and rendering process
            transformer.transform(src, res);

            //Prepare response
            response.setContentLength(out.size());
    
            //Send content to Browser
            response.getOutputStream().write(out.toByteArray());
            response.getOutputStream().flush();
        }
        catch (Exception ex){
            ex.printStackTrace();
        }        
    }
```

Das Problem ist, dass ich folgende Fehlermeldung erhalte:

STDERR] System-ID unbekannt; Zeilennummer1; Spaltennummer1; Content is not allowed in prolog.

Ich weiß mit diesem Fehler leider nichts anzufangen...
Hat einer von Euch nen Tipp für mich?

Gruß shocking


----------

