Nodes in Document kopieren, nur die Childs, die noch nicht existieren

Status
Nicht offen für weitere Antworten.

guni

Bekanntes Mitglied
Hallo,

ich habe ein root-Element aus einem Document.
dann habe ich eine Schleife, die wie folgt aussieht
Java:
while bedingung {
   Element e = generateElement();
   root.appendChild(e);
}
generateElement erzeugt ein XML das die folgende Struktur hat:
[XML]<one value="a">
<two value="d">
<three value="g">
<four value="j">
<five value="k">
<six value="l">
</three>
</two>
</one>[/XML]
mit root.appendChild hab ich das Problem, dass jedes dieser Elemente tatsächlich ins doc eingefügt wird; in Wirklichkeit will ich aber nur jene Elemente einfügen, die tatsächlich auch neu sind; d.h das Ganze soll so aussehen:
[XML]<root>
<one value="a">
<two value="d">
<three value="g">
<four value="j">
<five value="k">
<six value="l">
</three>
</two>
<two value="e">
<three value="g">
<four value="j">
<five value="k">
<six value="l">
</three>
<three value="h">
<four value="j">
<five value="k">
<six value="l">
</three>
</two>
</one>
<one value="b">
<two value="d">
<three value="g">
<four value="j">
<five value="k">
<six value="l">
</three>
</two>
</one>
</root>[/XML]
seht ihr worum es geht?
aufgrund des Value-Attributes einer Node soll die appendChild-Methode entscheiden, ob eine node bereits vorhanden ist, oder nicht.
wenn sie schon vorhanden ist, sollen die children erst ab da eingefügt werden, wo sie neu sind.

gibt es dafür schon irgendeine Funktion die das kann?
(document.adoptChild / document.importChild scheinen das nicht zu bewerkstelligen).
wenn es noch keine Funktion gibt: wie kann ich sowas sinnvoll schreiben?

danke für eure tipps!

mfg, guni
 

guni

Bekanntes Mitglied
hilfe! kennt sich da irgendwer aus?
ich probier schon ewig herum, aber ich komm einfach keinen schritt weiter!
 

guni

Bekanntes Mitglied
hallo Leute,

bin gestern noch eine Weile gesessen und hab das hier auf die Reihe gekriegt:

Java:
	private void addElement(Element parent, Element child) throws Exception 
	{
		if (child == null) return;
		
		Element e = findNode(parent, child);
		
		boolean nodeAlreadyExists = (child.getTagName().equals(e.getTagName()) && 
				child.getAttribute("value").equals(e.getAttribute("value")));
		
		if (nodeAlreadyExists) {
			addElement(child, (Element)child.getFirstChild());
		} else {
			e.appendChild(child);
		}
	}
	
	private Element findNode(Element parent, Element child) throws Exception
	{
		// wenn child unter parent existiert, 
		// dann gib child zurück, 
		// sonst gib parent zurück
		String childTagName = child.getTagName();
		String childValueAttribute = child.getAttribute("value");
		
		// wenn wir nichts anderes mehr finden, dann geben wir 
		// parent zurück
		Element found = parent;
		
		// finde alle Elemente im Dokument, die dem TagNamen des angegebenen
		// childs entrsprechen
		NodeList foundElements = parent.getElementsByTagName(childTagName);
		
		// wenn Elemente gefunden wurden, nehmen wir das, zu dem der value passt!
		if (foundElements.getLength() > 0) {
			for (int i=0; i<foundElements.getLength(); i++) { 
				Element x = (Element)foundElements.item(i);
				String _tagname = x.getTagName();
				// beim Value ist noch irgendein Fehler!
				String _value = x.getAttribute("value"); 
				if (_tagname.equals(childTagName) && _value.equals(childValueAttribute)) {
					found = x;
				}
			}
		}
		return found;
	}

mein Problem:
es funktioniert nicht! Ausserdem denk ich mir, es muss dort IRGENDEINE Methode geben, die genau dieses Problem löst! Es kann ja nicht sein, dass ich der erste bin, der sich mit Gruppierungen in XML herumärgert ...

mfg, simon
 

guni

Bekanntes Mitglied
kann mir da echt keiner weiterhelfen?
the_29 hat mir einen ganz guten Tipp gegeben; vielleicht werd ich den mal probieren ...
 

guni

Bekanntes Mitglied
... nur einiges an Code für ein Problem von dem ich dachte, dass es eigentlich trivial ist ...
 
B

Beni

Gast
Ich hätte die Methode "findNode" etwas anders geschrieben, so dass sie null zurückgibt wenn nichts gefunden wird. Ansonsten sehe ich gerade nicht was falsch läuft, kannst du vielleicht ein KSKB geben?
Java:
package tos_spielwiese;

import java.io.StringWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;


public class Test {
	public static void main(String[] args) throws Exception {
		DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		Document doc = builder.newDocument();
		
		Element root = createElement( "root", "?", doc );
		Element a = createElement( "one", "a", doc );
		Element b = createElement( "two", "b", doc );
		Element c = createElement( "two", "c", doc );
		Element d = createElement( "one", "b", doc );
		Element e = createElement( "two", "b", doc );
		Element f = createElement( "two", "b", doc );
		Element g = createElement( "three", "b", doc );
		
		addElement( root, a );
		addElement( a, b );
		addElement( a, c );
		addElement( root, d );
		addElement( d, e );
		addElement( f, g );
		addElement( d, f );
		
		println( root );
	}
	
	private static void println( Element node ) throws Exception{
		TransformerFactory transFactory = TransformerFactory.newInstance();
		Transformer transformer = transFactory.newTransformer();
		StringWriter buffer = new StringWriter();
		transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
		transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
		transformer.transform(new DOMSource(node),
		      new StreamResult(buffer));
		String str = buffer.toString();
		System.out.println( str );
	}
	
	private static Element createElement( String tag, String value, Document doc ){
		Element e = doc.createElement( tag );
		e.setAttribute( "value", value );
		return e;
	}
	
    private static void addElement(Element parent, Element child) throws Exception {
        if (child == null) 
        	return;
        
        Element next = findNode(parent, child);
        if( next == null ){
        	parent.appendChild( child );
        }
        else{
        	NodeList list = child.getChildNodes();
        	for( int i = 0, n = list.getLength(); i<n; i++ ){
        		addElement( next, (Element)list.item( i ) );
        	}
        }
    }
    
    private static Element findNode(Element parent, Element child) throws Exception
    {
        // wenn child unter parent existiert, 
        // dann gib child zurück, 
        // sonst gib parent zurück
        String childTagName = child.getTagName();
        String childValueAttribute = child.getAttribute("value");
        
        // finde alle Elemente im Dokument, die dem TagNamen des angegebenen
        // childs entrsprechen
        NodeList foundElements = parent.getElementsByTagName(childTagName);
        
        // wenn Elemente gefunden wurden, nehmen wir das, zu dem der value passt!
        if (foundElements.getLength() > 0) {
            for (int i=0; i<foundElements.getLength(); i++) { 
                Element x = (Element)foundElements.item(i);
                String _tagname = x.getTagName();
                // beim Value ist noch irgendein Fehler!
                String _value = x.getAttribute("value"); 
                if (_tagname.equals(childTagName) && _value.equals(childValueAttribute)) {
                    return x;
                }
            }
        }
        return null;
    }
}
 

guni

Bekanntes Mitglied
danke beni!

deine Methode funktioniert.
dummerweise bin ich gerade drauf gekommen, dass mir ein XML in der Form eigentlich nix bringt:

in der Praxis bekomme ich nämlich ein CSV mit Abwesenheiten von Mitarbeitern; vereinfacht gesagt sieht es so aus:

<DATUM>, <MITARBEITERNUMMER>, <ABWESENHEIT>:
0101, 1, KRANK
0201, 1, ANWESEND
0301, 1, ANWESEND
0401, 1, ANWESEND
0501, 1, ANWESEND
0601, 1, AUSSENDIENST
0701, 1, AUSSENDIENST
0801, 1, ANWESEND
0901, 1, ANWESEND
...
0101, 2, ANWESEND
0201, 2, ANWESEND
0301, 2, ANWESEND
0401, 2, ANWESEND
0501, 2, URLAUB
0601, 2, URLAUB
0701, 2, URLAUB
0801, 2, URLAUB
0901, 2, ANWESEND
...

meine Aufgabe ist es, eine CSV in folgender Form zu schreiben:
<MITARBEITER>, <VON>, <BIS>, <GRUND>:
1, 0101, 0101, KRANK
1, 0201, 0501, ANWESEND
1, 0601, 0701, AUSSENDIENST
1, 0801, 0901, ANWESEND
2, 0101, 0401, ANWESEND
2, 0501, 0801, URLAUB
2, 0901, 0901, ANWESEND

... natürlich ist das Problem in der Praxis noch etwas komplexer; die Kriterien, für die ein neuer Datumszeitraum definiert werden soll sind nicht nur
* "andere Mitarbeiternummer als in der Vorzeile" und
* "anderer Abwesenheitsgrund als in der Vorzeile"

also ... ich hab einen Ansatz, in dem ich meine CSV zeilenweise einlese, das result in einem gesplitteten String-Array speichere.
Dieses speichere ich wiederum in einer linked list. beginnt ein neuer Datumsblock (aufgrund verschiedener Kriterien, dann schreibe ich das resultat der linkedList mit VON=DATUM[LinkedList.getFirst] und BIS=DATUM[LinkedList.getLast]

... soweit klar, oder?

jetzt hab ich mir gedacht; das Ganze wäre doch viel schöner, wenn ich ein XML dazu bastle, dass ich dann einfach per XSL in eine CSV umwandle.

ich lese also die CSV ein und create mir für jeden String ein eigenes Element.
dann baue ich mir die Struktur so auf, wie sie mir gefällt:

Java:
grund.appendChild(vond);
penr.appendChild(grund);
finr.appendChild(penr);

damit erhalte ich folgende Xml-Struktur:
[XML]<FINR value="">
<PENR value="">
<VOND value=""/>
</PENR>
</FINR>[/XML]

über den Merge, den mir Beni obenstehend ausgebessert hat, erhalte ich nun eine XML- in der alle Daten gruppiert sind.
das sollte dann nach obenstehendem Beispiel für Mitarbeiter 1 so aussehen:

[XML]<FINR value="1">
<PENR value="1">
<GRUND value="KRANK">
<VOND value="0101"/>
</GRUND>
<GRUND value="ANWESEND">
<VOND value="0201"/>
<VOND value="0301"/>
<VOND value="0401"/>
<VOND value="0501"/>
<VOND value="0801"/>
<VOND value="0901"/>
</GRUND>
<GRUND value="AUSSENDIENST">
<VOND value="0601"/>
<VOND value="0701"/>
</GRUND>
</PENR>
</FINR>[/XML]

hey! seht ihr das Problem?!
ich kann unmöglich durch mein XML gehen und einfach sagen
VON = aktuellerGrund.getFirstChild();
BIS = aktuellerGrund.getLastChild();

das Problem ist, dass meine Sortierung verloren geht!
obenstehendes XML würde folgenden Output geben:

1, 0101, 0101, KRANK
1, 0201, 0901, ANWESEND
1, 0601, 0701, AUSSENDIENST

gewünscht ist aber natürlich folgender Output:

1, 0101, 0101, KRANK
1, 0201, 0501, ANWESEND
1, 0601, 0701, AUSSENDIENST
1, 0801, 0901, ANWESEND

mein XML müsste also eigentlich so aussehen:

[XML]<FINR value="1">
<PENR value="1">
<GRUND value="KRANK">
<VOND value="0101"/>
</GRUND>
<GRUND value="ANWESEND">
<VOND value="0201"/>
<VOND value="0301"/>
<VOND value="0401"/>
<VOND value="0501"/>
</GRUND>
<GRUND value="AUSSENDIENST">
<VOND value="0601"/>
<VOND value="0701"/>
</GRUND>
<GRUND value="ANWESEND">
<VOND value="0801"/>
<VOND value="0901"/>
</GRUND>
</PENR>
</FINR>[/XML]

hat von euch wer eine Idee dazu?!
muss ich meinen Ansatz jetzt völlig verwerfen?
XML hat mir so viel schöner ausgesehen wie meine blöden LinkedLists für die Datumsblöcke!!

mfg, guni
 
Zuletzt bearbeitet:
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
S NodeList rückwärts scannen, alle Parent Nodes ausgeben rekursiv und nicht-reukrsiv XML & JSON 0
A XML schaffe es nicht Nodes auszulesen XML & JSON 5
G xquery - nodes unterscheiden sich nur durch attribute :-( XML & JSON 4
M dom nodes vs. elements? XML & JSON 2
S XML Document Parsen und Ausgeben mit Suchfunktion XML & JSON 21
L XML Document Transform StackOverflowError XML & JSON 1
B Wie kann man das ecncoding in einem vorhandenen Document-Objekt ändern? XML & JSON 2
M java.lang.RuntimeException: Failed to parse document XML & JSON 4
sylo DOM Document in XML Datei schreiben XML & JSON 5
sambalmueslie JAXB - Unmarshall ein XML-Document das aus zwei XSD Definitionen besteht XML & JSON 8
L invalide xml document parsen?! XML & JSON 2
K Document null bei builder.parse XML & JSON 2
B jdom document aus string erzeugen? XML & JSON 1
G document is invalid: no grammar found. XML & JSON 9
M Wie kann ich aus ein Document-Tree ein PDF generieren XML & JSON 2
G Ein DOM-Document dem Sax übergeben? XML & JSON 2
S org.jdom.document in String umwandeln. XML & JSON 2
P Aus einem Node ein Document erstellen XML & JSON 2
R XML Document als String XML & JSON 2
C Kompliziertes XML-Document, wie lese ich es ein? XML & JSON 4
N FileStream auf Document XML & JSON 22
M XPath Problem im Zusammenhang mit document() XML & JSON 2
B XML-Document mit Java erzeugen und zuruecksenden XML & JSON 1
W XML-Document auslesen XML & JSON 2
S mit dom4j einen dom teilweise kopieren? XML & JSON 4
M JDOM Element ohne Inhalt kopieren ? XML & JSON 3
N Node unter anderem Namen kopieren XML & JSON 3

Ähnliche Java Themen

Neue Themen


Oben