Java XML-Element ersetzen und in xslt umwandeln

furryhamster

Lt. Commander
Registriert
Okt. 2008
Beiträge
1.101
Hi,

ich hab xml und möchte dies mit java automatisch in ein xslt umwandeln.

Beispiel-XMLausschnitt:
Code:
<w:p w:rsidR="000F1E17" w:rsidRDefault="000F1E17" w:rsidP="000F1E17">
	<w:r>
		<w:t>Nachname:</w:t>
	</w:r>
	<w:r>
		<w:tab/>
	</w:r>
	<w:fldSimple w:instr=" INCLUDETEXT  &quot;C:/XML/daten.xml&quot; \c XML \x /ADRESSEN/DATENSATZ[2]/NACHNAME  \* MERGEFORMAT ">
		<w:r w:rsidR="008D563D">
			<w:t>Meier</w:t>
		</w:r>
	</w:fldSimple>
</w:p>

In dem Beispiel soll jetzt z.B. Meier durch folgendes ersetzt werden:
<xsl:value-of select="string($var1_instance/n2:ClinicalDocument/n2:title)"/>

Ergebnis soll folglich so aussiehen:
Code:
<w:p w:rsidR="000F1E17" w:rsidRDefault="000F1E17" w:rsidP="000F1E17">
	<w:r>
		<w:t>Nachname:</w:t>
	</w:r>
	<w:r>
		<w:tab/>
	</w:r>
	<w:fldSimple w:instr=" INCLUDETEXT  &quot;C:/XML/daten.xml&quot; \c XML \x /ADRESSEN/DATENSATZ[2]/NACHNAME  \* MERGEFORMAT ">
		<w:r w:rsidR="008D563D">
			<w:t><xsl:value-of select="string(  /ADRESSEN/DATENSATZ[2]/NACHNAME )"/></w:t>
		</w:r>
	</w:fldSimple>
</w:p>

Problem: Wenn ich das "Meier" mit setTextConent() ersetze, so fällt das w:r und w:t element wer und er schreibt mit auch die <> von xsl:value-of selec nicht in mein xslt file

Mein Lösungsansatz:
Code:
newContent = "<w:r w:rsidR=\"008D563D\"><w:t><xsl:value-of select=\"string( " + m.group(1) + ")\"/></w:t></w:r>";

document.getElementsByTagName("w:fldSimple").item(i).setTextContent(newContent);

Mein Ergebnis:
Code:
<w:fldSimple w:instr=" INCLUDETEXT  &quot;C:/XML/daten.xml&quot; \c XML \x /ADRESSEN/DATENSATZ[2]/NACHNAME  \* MERGEFORMAT "> /ADRESSEN/DATENSATZ[2]/NACHNAME</w:fldSimple>

Weiß einer wie ich das jetzt ersetzen muss?
Kann mir auch jemand sagen, wie ich in dem "document" das "<?xml version="1.0" encoding="UTF-8"?>" durch
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:n2="urn:hl7-org:v3"
exclude-result-prefixes="n2 xs xsi xsl"
>
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">

ersetze und am ende des XML Files
</xsl:template>
</xsl:stylesheet>

anhänge?


EDIT: Habs hinbekommen, indem ich ein Child hinzugefügt habe. Jetzt muss ich nur noch die erste xml zeile ersetzen und am ende etwas anhängen
 
Zuletzt bearbeitet:
Kleiner Hinweis nebenbei: Was du da benutzt, ist Javascript, nicht Java. Die Sprachen ähneln sich zwar vom Namen her, sind aber ansonsten völlig unterschiedlich :)
 
NullPointer schrieb:
Kleiner Hinweis nebenbei: Was du da benutzt, ist Javascript, nicht Java. Die Sprachen ähneln sich zwar vom Namen her, sind aber ansonsten völlig unterschiedlich :)

LOL, auch für Java gibt es DOM APIs... Außerdem wird er wohl wissen, welche Sprache er zum Coden benutzt :p
 
Ich hab nicht behauptet, es gäbe keine DOM APIs für Java. Aber wenn sein Lösungsansatz so aussieht:

Code:
document.getElementsByTagName("w:fldSimple").item(i).setTextContent(newContent);

dann ist das kein Java :)
 
NullPointer schrieb:
Ich hab nicht behauptet, es gäbe keine DOM APIs für Java. Aber wenn sein Lösungsansatz so aussieht:

Code:
document.getElementsByTagName("w:fldSimple").item(i).setTextContent(newContent);

dann ist das kein Java :)

läuft in meinen .javadateien jedenfalls wunderbar und läuft auch zusammen mit den anderen javafunktionen rund ;)

ich habe übringens das problem soweit gelöst. allerdings bin ich mit meiner lösung noch nicht so ganz zufrieden. da die xmldatei in einer einzigen zeile vorliegt, mache ich einen substring darauf, um das übliche <?xml version="1.0" encoding="UTF-8"?> zu entfernen. lieber wäre es mir ich würde jede jede zeile (ich lese zeilenweise ein) auf diesen string prüfen und ggf. entfernen können. leider hat das mit replace nicht geklappt. er entfernt den string nicht. jemand ne idee?
 
Das mir solche Bruchstücke in Java laufen wäre mir neu. Den code würde ich liebend gern mal sehen.

€dit: Bruchstücke sind etwas "falsch" ausgedrückt. Das ist javascript-Code. Mir wäre absolut neu, das der Java-Interpreter etwas mit "document" oder eine Methode "getElementyByTagName" anfangen könnte. Aber ich lass mich gern eines besseren belehren.

€dit2: Jetzt bin ich wirklich etwas geschockt.
http://www.java2s.com/Code/JavaAPI/org.w3c.dom/DocumentgetElementsByTagNameStringtagname.htm
 
Zuletzt bearbeitet:
Das ist natürlich nur ein Code-Fragment. Die Variablendeklaration musst Du Dir dazu denken. Ansonsten ist das die Standard DOM API und jede Menge verkettete Methodenaufrufe. Daran ist jetzt wirklich nichts ungewöhnliches.
 
chriz0101 schrieb:
Mir wäre absolut neu, das der Java-Interpreter etwas mit "document" oder eine Methode "getElementyByTagName" anfangen könnte. Aber ich lass mich gern eines besseren belehren.

"document" ist in meinem Fall ein "Document" vom DocumentBuilder

soares schrieb:

Momentan löse ich das Problem so:
Code:
while ((line = in.readLine()) != null) {
	if (line.substring(0, 38).equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") ) {
		line = addBegin + line.substring(38) + addEnd;
		break;
	}
}

Derzeit ist das komplette xml in einer einzigen Zeile. Falls sich dies mal ändern sollte, habe ich die while-Schleife. Da ich vermute, dass "<?xml version="1.0" encoding="UTF-8"?>" immer in einer Zeile sein wird, hätte ich gern eine Lösung, die jede Zeile nach diesem String sucht und dies ggf. aus dem String entfernt.
 
Okay, ich hab mich wohl zu weit aus dem Fenster gelehnt. Aber bei "document.getElementsByTagName()" denken sicher die meisten Programmierer zuerst mal an Javascript :)
 
furryhamster schrieb:
Momentan löse ich das Problem so:
Code:
while ((line = in.readLine()) != null) {
	if (line.substring(0, 38).equals("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") ) {
		line = addBegin + line.substring(38) + addEnd;
		break;
	}
}

Derzeit ist das komplette xml in einer einzigen Zeile. Falls sich dies mal ändern sollte, habe ich die while-Schleife. Da ich vermute, dass "<?xml version="1.0" encoding="UTF-8"?>" immer in einer Zeile sein wird, hätte ich gern eine Lösung, die jede Zeile nach diesem String sucht und dies ggf. aus dem String entfernt.

Mit Vermutungen ist das immer so eine Sache. Wenn sichergestellt ist, dass die Deklaration immer in einer kompletten Zeile vorliegt, mag es angehen, jede Zeile zu durchsuchen. Ich würde bei sowas aber auf Nummer sicher gehen, und über die komplette Datei suchen. Die XML Deklaration sollte doch nur einmal vorkommen?

PHP:
String input = ...;
Pattern p = Pattern.compile("^\\s*<\\?xml(.*?)>\\s*", Pattern.DOTALL);
Matcher m = p.matcher(input);

input = m.replaceAll("");

Danach kann man immer noch zeilenweise über den Text gehen, wenn notwendig. Wobei ich bei XML-Dateien eine entsprechende API einsetzen würde. Lustigerweise willst Du ja ein XSL-Dokument erstellen. Warum nicht XSLT dafür verwenden?

Den obigen Code kannst Du auch zum Suchen&Ersetzen beim zeilenweisen Vorgehen verwenden:

PHP:
Pattern p = Pattern.compile("<\\?xml(.*?)>");
Matcher m = p.matcher("");

while ((line = in.readLine()) != null) {
    m.reset(line);
    line = m.replaceFirst("");
}

Aber wie gesagt, besonders robust ist das nicht.
 
Genau, die XML Deklaration kommt nur 1x vor. Und genau wegen der von dir genannten Problematik möchte ich meinen Teil Code ersetzen.

Bei deiner Methode sehe ich das Problem, dass ich nicht weiß wie ich das komplette Dokument einlese. Ich arbeite noch nicht lange damit und beherrsche es nur grundlegend. Ich habe nur Lösungen zum einlesen Zeichen- und Zeilenweise gefunden.

Für das xml-Dokument erzeuge ich ein xslt Datei. Das Programm arbeitet im groben wie folgt:
1. Entpacken der document.xml aus dem docx-Template
2. Ich ersetze den Inhalt mit XPath ausdrücken, die ich vorher über Felder in Word definiert habe
3. Ich entferne die XML Deklaration hänge am Anfang und Ende den oben genannten Code an
4. Ich transformiere mit Hilfe des Templates, der xslt und der Daten-XML die Daten zu einem Openxml docx Dokument
 
furryhamster schrieb:
Genau, die XML Deklaration kommt nur 1x vor. Und genau wegen der von dir genannten Problematik möchte ich meinen Teil Code ersetzen.

Bei deiner Methode sehe ich das Problem, dass ich nicht weiß wie ich das komplette Dokument einlese. Ich arbeite noch nicht lange damit und beherrsche es nur grundlegend. Ich habe nur Lösungen zum einlesen Zeichen- und Zeilenweise gefunden.

Du musst die Zeichen/Zeilen nur in einen StringBuilder packen und diesen an den Matcher weiterreichen.

PHP:
StringBuilder buf = new StringBuilder();

while ((line = in.readLine()) != null) {
    buf.append(line).append('\n');
}

Pattern p = ...;
Matcher m = p.matcher(buf);
String input = m.replaceFirst("")

Um Textdateien einzulesen, kann man z.B. so vorgehen.

PHP:
public static String readText(final File rFile)
    throws IOException
{
    if (!rFile.exists())
    {
        throw new FileNotFoundException("File does not exist: " + rFile);
    }

    if (rFile.length() > Integer.MAX_VALUE)
    {
        throw new IllegalArgumentException("Can only handle files up to "
            + Integer.MAX_VALUE + " bytes, was " + rFile.length() + " bytes");
    }

    Reader in = new BufferedReader(new InputStreamReader(
                new FileInputStream(rFile), "UTF-8"));

    try
    {
        int length = (int) rFile.length();

        char[] buf = new char[length];
        in.read(buf, 0, length);

        return new String(buf);
    }
    finally
    {
        in.close();
    }
}

Es gibt dafür unzählige Beispiele und fertige Sachen wie Commons IO, die man unbesehen verwenden kann.
 
Zurück
Oben