Замена символов в неправильно сформированном теле XML

В (Java) коде, над которым я работаю, я иногда имею дело с не правильно сформированным XML (представленным как Java String), такие как:

<root>
  <foo>
    bar & baz < quux
  </foo>
</root>

Так как этот XML в конечном итоге должен быть распакован (с использованием JAXB), очевидно, что этот XML как есть, выдаст исключение при распаковке.

Какой лучший способ заменить & и < своим персонажем сущностей? За &это так же просто, как:

xml.replaceAll("&", "&amp;")

Однако для < символ, это немного сложно, так как, очевидно, я не хочу заменять < это используется для открытия тега XML 'скобка'.

Кроме сканирования строки и замены вручную < в теле XML с &lt;Какой другой вариант вы можете предложить?

3 ответа

Решение

Честно говоря, лучший способ исправить искаженный XML - это отправить его обратно тому, кто его создал, и попросить вместо этого выслать вам правильно сформированный XML. Вы показываете тривиальный пример, который потенциально может иметь решение, но общий метод исправления искаженного XML будет ужасной работой.

А так как синтаксические анализаторы XML не обязаны обрабатывать искаженный XML, ваш синтаксический анализатор также не требуется. Просто не делай этого.

Я думаю, вам нужно больше логики заранее. Лучше всего сначала найти все реальные теги, используя регулярное выражение типа "(<[^>] +>)", и заменять только текст вне этих совпадений, но, очевидно, вы не сможете использовать метод replaceAll. Это будет больше работа сантехника...

Хотя это старый пост, но я подумал, что это может помочь кому-то еще... У меня было такое же требование / проблема, и я мог решить, используя следующий код.

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


public class XMLTest {

/**
* @param args
*/

public static void main(String[] args) {

String xml = "<xml><body>" +
"<message>something < between <<<  somthing </message>" +
"<text> testing  >> > testing </text>" +
"</body></xml>";

Pattern replaceGTPattern = Pattern.compile(">[^<](.[^<]*)(>)+");

Matcher m = replaceGTPattern.matcher(xml);

String replacement;
StringBuffer intermXml = new StringBuffer();


while(m.find()){

    replacement = ">"+m.group(0).substring(1).replaceAll(">", ";&gt");


    m.appendReplacement(intermXml,replacement);


    }


    m.appendTail(intermXml);

Pattern replaceLTPattern = Pattern.compile("<(.[^>]*)(<)+");

m = replaceLTPattern.matcher(intermXml);

StringBuffer finalXml = new StringBuffer();

while(m.find()){

    replacement = m.group(0).substring(0,m.group(0).length()-1).replaceAll("<", ";&lt").concat("<");


    m.appendReplacement(finalXml,replacement);


    }

    m.appendTail(finalXml);

    System.out.println(finalXml);

}
}
Другие вопросы по тегам