Замена символов в неправильно сформированном теле XML - PullRequest
1 голос
/ 09 июня 2010

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

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

Поскольку этот XML в конечном счете необходимо будет демаршировать (используя JAXB), очевидно, что этот XML как есть, будет генерировать исключение при демаршаллинге.

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

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

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

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

Ответы [ 3 ]

4 голосов
/ 10 июня 2010

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

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

1 голос
/ 04 февраля 2011

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

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);

}
}
1 голос
/ 09 июня 2010

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

...