# Mehrfaches Character-Replacement in einem String - Effizienz?



## dlk94mylis (7. Mai 2007)

Hi,

Ich muss aus einem String, welcher pseudo-xml enthält, ein vernünftiges xml-doc bauen. Tollerweise enthält der String allemöglichen Sonderzeichen: öäü ' ß & _ etc.pp...
Die muss ich nun in xml-valide ketten ersetzen, zb. alle ü in ü.

Das würde zu folgendem führen:

```
result = result.replace("&uuml;", "ü");
                result = result.replace("&Uuml;", "&#220");
                result = result.replace("&auml;", "&#228");
                result = result.replace("&Auml;", "&#196");
                result = result.replace("&ouml;", "&#246");
                result = result.replace("&Ouml;", "&#214");
                result = result.replace("&szlig;", "&#223");
                
                result = result.replace("ü", "ü");
                result = result.replace("Ü", "&#220");
                result = result.replace("ä", "&#228");
                result = result.replace("Ä", "&#196");
                result = result.replace("ö;", "&#246");
                result = result.replace("ö", "&#214");
                result = result.replace("ß", "&#223");

                result = result.replace("'", "&apos");
                result = result.replace("&", "&amp;");
                result = result.replace("\"", "&quot;");
```

Kann man das irgendwie performanter machen? schließlich geht er so den kompletten String n mal durch....zwar immer noch linear, aber dennoch nich doll, oder?

Thnx!


----------



## limago (7. Mai 2007)

Wieso benutzt Du nicht einen vernünftigen DOM-Parser. Damit hast Du das Problem gar nicht, weil der Parser das für Dich löst. JDom sollte das können :

http://www.galileocomputing.de/open...13_006.htm#mj08909522f0e2cb10c8ace6f924e5b094

Wenn das nicht für Dich in Frage kommt, solltest Du das mit regulären Ausdrücken lösen. Mittlerweile gibt es ja auch in Java eine RegEx-Engine. ;-)

Grüße

Jo

P.S. Noch ein bischen Code dazu:



package de.limago;

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


public class DomDemo {


	public static void main(String[] args) throws Exception {

		Document doc = new Document();

		Element element = new Element("root");
		doc.addContent(element);

		element.addContent("& \"  < > etc.");

		XMLOutputter out = new XMLOutputter(); 
		out.output( doc, System.out );

	}


}

macht folgende Ausgabe:

<?xml version="1.0" encoding="UTF-8"?>
<root>&amp; "  &lt; &gt; etc.</root>


----------



## Thomas Darimont (7. Mai 2007)

Hallo,

flotter würde es gehen, wenn du das ganze in einen StringBuilder steckst... implizit werden bei String.replace immer komplett neue String Instanzen erzeugt...
http://www.tutorials.de/forum/java/269458-html-entities-zeichen-umwandeln.html

Gruß Tom


----------



## limago (8. Mai 2007)

Hi,

ich wollte es genau wissen und habe die Performance gemessen. Der Stringbuilder ist 4 mal schneller als RegEx und 5 mal schneller als die Stringlösung. Ich bin beeindruckt...


```
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Tester {

	static Map<String, String> characterToEntityMap = new HashMap<String, String>();
	static Map<Pattern, String> patternMap = new HashMap<Pattern, String>();
	
	static {
		
		characterToEntityMap.put("ü", "ü");
		characterToEntityMap.put("Ü", "Ü");
		characterToEntityMap.put("ä", "ä");
		characterToEntityMap.put("Ä", "Ä");
		characterToEntityMap.put("ö;", "ö");
		characterToEntityMap.put("ö", "Ö");
		characterToEntityMap.put("ß", "ß");

		characterToEntityMap.put("'", "&apos;");
		characterToEntityMap.put("&", "&amp;");
		characterToEntityMap.put("\"", "&quot;");

		patternMap.put(Pattern.compile("ü"), "ü");
		patternMap.put(Pattern.compile("Ü"), "Ü");
		patternMap.put(Pattern.compile("ä"), "ä");
		patternMap.put(Pattern.compile("Ä"), "Ä");
		patternMap.put(Pattern.compile("ö;"), "ö");
		patternMap.put(Pattern.compile("ö"), "Ö");
		patternMap.put(Pattern.compile("ß"), "ß");

		patternMap.put(Pattern.compile("'"), "&apos;");
		patternMap.put(Pattern.compile("&"), "&amp;");
		patternMap.put(Pattern.compile("\""), "&quot;");

	}
	
	public static void main(String[] args) {

		for (int i = 0; i < 20; i++) {

			long start = System.currentTimeMillis();
			for (int j = 0; j < 10000; j++) {
				String result;

				result = "üäÄÖüäÄÖüäÄÖüäÄÖüäÄÖüäÄÖüäÄÖüäÄÖ";

				result = result.replace("ü", "ü");
				result = result.replace("Ü", "Ü");
				result = result.replace("ä", "ä");
				result = result.replace("Ä", "Ä");
				result = result.replace("ö;", "ö");
				result = result.replace("ö", "Ö");
				result = result.replace("ß", "ß");

				result = result.replace("'", "&apos;");
				result = result.replace("&", "&amp;");
				result = result.replace("\"", "&quot;");

			}
			long end = System.currentTimeMillis();
			System.out.println("Replace mit String:" + (end - start)
					+ " millis");
		}

		for (int i = 0; i < 20; i++) {
			
			long start = System.currentTimeMillis();
			for (int j = 0; j < 10000; j++) {
				String result=null;

				result = "üäÄÖüäÄÖüäÄÖüäÄÖüäÄÖüäÄÖüäÄÖüäÄÖ";
				result = escapeHtmlSpecialChars(result);
			}
			long end = System.currentTimeMillis();
			
			System.out.println("Replace mit Stringbuilder:" + (end - start)
					+ " millis");
		}
		
		for (int i = 0; i < 20; i++) {
			StringBuffer result=null;
			long start = System.currentTimeMillis();
			for (int j = 0; j < 10000; j++) {
				

				result = new StringBuffer("üäÄÖüäÄÖüäÄÖüäÄÖüäÄÖüäÄÖüäÄÖüäÄÖ");
				for(Pattern p : patternMap.keySet()) {
					Matcher m = p.matcher(result);
					 StringBuffer sb = new StringBuffer();
					 while (m.find()) {
					     m.appendReplacement(sb, patternMap.get(p));
					 }
					 m.appendTail(sb);
					 result = sb;
				}
				 
			}
			long end = System.currentTimeMillis();
			System.out.println("Replace mit RegEx:" + (end - start)
					+ " millis");
		}

	}
	
	

	public static String escapeHtmlSpecialChars(String htmlString) {
		StringBuilder stringBuilder = new StringBuilder();
		for (char c : htmlString.toCharArray()) {
			String characterString = String.valueOf(c);
			if (isHtmlSpecialCharacter(c)) {
				//stringBuilder.append("&");
				stringBuilder.append(characterToEntityMap
						.get(characterString));
				//stringBuilder.append(";");
			} else {
				stringBuilder.append(c);
			}
		}
		return stringBuilder.toString();
	}

	private static boolean isHtmlSpecialCharacter(char c) {
		return characterToEntityMap.containsKey(String.valueOf(c))
				|| c < ' ';
	}
}
```


----------

