<?xml version=\"1.0\" encoding=\"euc-kr\"?><root><data>한{글1234 5678  English日本0A</data></root>
이런 XML을 파싱을 하다 보면...
[Fatal Error] :4:13: Character reference "" is an invalid XML character.
org.xml.sax.SAXParseException: Character reference "" is an invalid XML character.
at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
at cis.jcaps.app.XMLParserTest.handle(XMLParserTest.java:75)
at cis.jcaps.app.XMLParserTest.doIt(XMLParserTest.java:53)
at cis.jcaps.app.XMLParserTest.main(XMLParserTest.java:177)
이런 에러가 납니다.
바로  요놈!. 특수문자가 변환된 놈 때문이지요..
이걸 HTML 파일로 저장해서 보면..
이렇게 보입니다.. 꼭 벌레같다는..
암튼. 저 데이터를 XML로 변환을 하면..  가 되지요.
이  를 다시 원래 벌레로 만들려면 XML 파서가 바로 위 같은 에러를 뱉어냅니다.
이 문제를 해결하기 위해서..
final Pattern nonValidPattern = Pattern.compile("&#(x?)([0-9a-fA-F]+);");
public String stripNonValidXMLCharacters(String str) {
StringBuffer out = new StringBuffer();
Matcher matcher = nonValidPattern.matcher(str);
int value = 0;
boolean isHex = false;
boolean valid = false;
while (matcher.find())
{
isHex = matcher.group(1) != null;
value = Integer.parseInt(matcher.group(2), isHex ? 16 : 10);
valid = false;
if ((value == 0x9) ||
(value == 0xA) ||
(value == 0xD) ||
((value >= 0x20) && (value <= 0xD7FF)) ||
((value >= 0xE000) && (value <= 0xFFFD)) ||
((value >= 0x10000) && (value <= 0x10FFFF)))
valid = true;
if (!valid)
matcher.appendReplacement(out, "");
}
matcher.appendTail(out);
return out.toString();
}
이 method를 사용하면 됩니다.
"&#(x?)([0-9a-fA-F]+);"
바로 이 패턴을 이용하여, &#xx; 이런식의 문자열을 지워버리는거죠.
&#로 시작하고,
&#뒤에 x가 0번 혹은 1번만 나오고.
&#뒤에 뒤에 숫자, 또는 영문자 a~f 까지만 허용되는 문자열이 1번 이상 나오고,
마지막은 ; 로 끝나는 문자열을 찾는거죠.
해당 문자열을 찾은 후에
if ((value == 0x9) ||
(value == 0xA) ||
(value == 0xD) ||
((value >= 0x20) && (value <= 0xD7FF)) ||
((value >= 0xE000) && (value <= 0xFFFD)) ||
((value >= 0x10000) && (value <= 0x10FFFF)))
valid = true;
이 루틴을 이용해서, XML 파싱에 허용되는 문자들만 거르게 되는겁니다!! 냐하하하.