PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RegEx



fallow
09-10-2007, 12:09
Hey,

ich habe ein Problem mit Java, XML und Regular Expressions: Ich will in einem XML-Fragment Tag-Namen ändern z.B.

<bla><blabla>data</blabla></bla>

zu


<10:bla><10:blabla>data</10:blabla></10:bla>


Ich habe folgenden Code für die Startags geschrieben. Der Matcher findet die entsprechenden Pattern. Das Problem ist, dass ich damit in eine Endlosschleife laufe, da nach dem replaceAll ja wieder neue Tags entstehen, die vom Matcher gefunden werden etc.



import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegEx {

static String getNewStartTag(String s){
int a = s.length();
String string = s.substring(1, a-1);
string = ("<10:"+string+">");
return string;
}

public static void main(String[] args) {
StringBuffer s = new StringBuffer("<bla><blabla>data</blabla></bla>");
Pattern startTag = Pattern.compile("<\\w+>");
Matcher matcher = startTag.matcher(s);
String tmp = null;
while(matcher.find()){
tmp = s.substring(matcher.start(), matcher.end());
matcher.replaceAll(getNewStartTag(tmp));
}
System.out.println(s.toString());
}

}

Hat vielleicht jemand eine tolle Idee, das Problem zu umgehen ?

Danke,
lars

mehlvogel
09-10-2007, 16:41
Ist es von den Daten her möglich dass du den Regulären Ausdruck so einschränkst, dass er nur auf Tags zutrifft, die keinen Doppelpunkt beinhalten? Ich bin in Sachen Regex leider nicht Experte genug, um dir das Pattern hier so hinzuklatschen.

jan61
09-10-2007, 21:29
Moin,

am regulären Ausdruck kann es eigentlich nicht liegen, "\w+" matcht ja nur auf alphanumerische Zeichen plus "_". Dein Problem liegt wohl eher darin, dass die Methode Matcher.replaceAll() den veränderten String als Returncode liefert. Da müsste bei Dir also sowas stehen wie "String result = matcher.replaceAll(...);".

Aber warum so kompliziert? Du musst doch nicht mühsam nach dem nächsten zu ersetzenden Tag suchen, wenn Du den regulären Ausdruck geschickt wählst.

Das ganze Geraffel mit Pattern und Matcher ist schon fertig in der String-Klasse gekapselt (ich habe mal als Beispiel den Fall mit reingenommen, dass ein Tag schon einen Doppelpunkt enthält):

public class RegexTest {

public static void main(String[] args) {
String s = "<bla><blabla>data</blabla></bla>";
String out = s.replaceAll("<(/?)(\\w+)>", "<$110:$2>");
System.out.println(out);
s = "<b:la><blabla>data</blabla></b:la>";
out = s.replaceAll("<(/?)(\\w+)>", "<$110:$2>");
System.out.println(out);
}

}
Das liefert:

<10:bla><10:blabla>data</10:blabla></10:bla>
<b:la><10:blabla>data</10:blabla></b:la>
Die Parameter des replaceAll:

"<(/?)(\\w+)>" = Alle Ausdrücke, die mit einem "<" beginnen, dann kein oder 1 "/" haben, dann 1..n alphanumerische Zeichen und dann ein ">". Die () bilden eine Gruppierung, auf die man dann im 2. Argument mit $1 ... $n (je nach Anzahl der ()-Paare) referenzieren kann.

Im 2. Parameter wird dann genau diese Referenz genutzt, um das Replacement zusammenzubauen. Also: Ersetze die gefundene Stelle mit einem "<", dann dem Inhalt der Referenz $1 (entweder leer oder ein "/" beim schließenden Tag), dann der Zeichenkette "10:", dann dem Inhalt der Referenz $2 und dann einem ">".

Jan

EDIT: Wenn Du - aus was für Gründen auch immer, zwingend mit den Pattern- und Matcher-Klassen arbeiten willst / musst:
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegexTest {

public static void main(String[] args) {
StringBuffer s = new StringBuffer("<bla><blabla>data</blabla></bla>");
Pattern startTag = Pattern.compile("<(/?)(\\w+)>");
Matcher matcher = startTag.matcher(s);
String tmp = matcher.replaceAll("<$110:$2>");
System.out.println(tmp);
}
}

panzi
13-10-2007, 03:09
Wenn du eh XML hast dann verwende doch eine XML API! DOM oder SAX. Damit lässt sich das schön umwandeln. Einfach einen SAX filter implementieren.

Vorlesungsfolien die's erklärn: http://www.dbai.tuwien.ac.at/education/ssd/folien/SAX.pdf
Beispieldatein: http://www.dbai.tuwien.ac.at/education/ssd/beispiele/Beispiele05.zip

Alle Folien zur Vorlesung: http://www.dbai.tuwien.ac.at/education/ssd/#Termine

Eine andere Idee wäre XSLT zu verwenden. Kann man auch von java aus anstoßen.
Folien: http://www.dbai.tuwien.ac.at/education/ssd/folien/XSLT.pdf
Beispiele: http://www.dbai.tuwien.ac.at/education/ssd/beispiele/Beispiele07.zip

Diese Vorlesung+Übung war so sau einfach. :)