Чтение узлов документов XML, содержащих специальные символы (&, - и т. Д.), С использованием Java - PullRequest
1 голос
/ 04 февраля 2012

Мой код не получает всю совокупность узлов элементов, которые содержат специальные символы.Например, для этого узла:

<theaterName>P&G Greenbelt</theaterName>

Он будет получать только «P» из-за амперсанда.Мне нужно получить всю строку.

Вот мой код:

public List<String> findTheaters() {

    //Clear theaters application global
    FilmhopperActivity.tData.clearTheaters();

    ArrayList<String> theaters = new ArrayList<String>();

    NodeList theaterNodes = doc.getElementsByTagName("theaterName");

    for (int i = 0; i < theaterNodes.getLength(); i++) {

        Node node = theaterNodes.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE) {

            //Found theater, add to return array
            Element element = (Element) node;
            NodeList children = element.getChildNodes();
            String name = children.item(0).getNodeValue();
            theaters.add(name);

            //Logging
            android.util.Log.i("MoviefoneFetcher", "Theater found: " + name);

            //Add theater to application global
            Theater t = new Theater(name);
            FilmhopperActivity.tData.addTheater(t);
        }
    }

    return theaters;
}

Я попытался добавить код для расширения строки имени, чтобы объединить дополнительные children.items, но это не сработало.Я бы получил только "P &".

...
String name = children.item(0).getNodeValue();
for (int j = 1; j < children.getLength() - 1; j++) {
    name += children.item(j).getNodeValue();
}

Спасибо за ваше время.


ОБНОВЛЕНИЕ: Найдена функция под названием normalize (), которую вы можете вызывать на узлах, которая объединяетвсе текстовые дочерние узлы, поэтому при выполнении children.item (0) содержится текст всех дочерних узлов, включая амперсанды!

Ответы [ 4 ]

5 голосов
/ 04 февраля 2012

& является escape-символом в XML. XML, который выглядит так:

<theaterName>P&G Greenbelt</theaterName>

должен быть фактически отклонен парсером. Вместо этого это должно выглядеть так:

<theaterName>P&amp;G Greenbelt</theaterName>

Есть несколько таких символов, таких как < (& lt;), > (& gt;), " (& quot;) и ' (''). Есть и другие способы экранирования символов, например, через их значение Unicode, как в & # x2022; или 〹.

Для получения дополнительной информации, спецификация XML довольно ясна.

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

Например, при использовании SAX для построения дерева сущности (& -веции) разбиваются на части и доставляются отдельно. Это связано с тем, что синтаксический анализатор SAX пытается вернуть непрерывные порции данных, а когда он попадает к escape-символу, он отправляет то, что имеет, и запускает новый порог с переведенным значением &. Поэтому вам может потребоваться объединить последовательные текстовые узлы в вашем дереве, чтобы получить все значение.

2 голосов
/ 04 февраля 2012

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

Я динамически извлекаю свой XML из Интернета. Каков наилучший способ заменить все мои escape-символы после получения объекта Document?

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

Если вы решили проигнорировать этот совет, то один из подходов заключается в чтении файла в строку, используйте String.replaceAll (регулярное выражение, замена) с подходящим регулярным выражением, чтобы превратить эти поддельные "&" символы в надлежащие символьные объекты ("&amp;"), затем передайте фиксированную строку XML анализатору XML. Вы должны тщательно спроектировать регулярное выражение, чтобы оно не нарушало действительные сущности персонажа как нежелательный побочный эффект. Второй подход заключается в том, чтобы выполнить синтаксический анализ и замену вручную, используя соответствующую эвристику, чтобы отличить фиктивных "&" символов от правильно сформированных символов.

Но все это стоит вам времени на разработку и тестирование и замедляет работу вашего программного обеспечения. Хуже того, существует значительный риск того, что ваш код будет хрупким в результате ваших усилий по компенсации плохих входных файлов. (И угадайте, кто получит вину ...)

0 голосов
/ 04 февраля 2012

Числовые ссылки на символы "&#60;" и "&#38;" могут использоваться для экранирования <</strong> и & , когда они встречаются в символьных данных.
Все XML процессоры ДОЛЖНЫ распознавать эти объекты независимо от того, объявлены они или нет. Для совместимости действительные документы XML ДОЛЖНЫ объявлять эти объекты, как и любые другие, перед их использованием. Если объекты lt или amp объявлены, они ДОЛЖНЫ быть объявлены как internal entities, чей замещающий текст представляет собой символьную ссылку на соответствующий символ (знак меньше или амперсанд) экранирование; двойное экранирование для этих объектов REQUIRED, так что ссылки на них дают хорошо сформированный результат. Если объекты gt, apos или quot объявлены, они ДОЛЖНЫ быть объявлены как internal entities, чей текст замены - экранированный одиночный символ (или символьная ссылка на этот символ; двойной выход здесь НЕОБЯЗАТЕЛЬНЫЙ, но безвредный). Например:

<!ENTITY lt     "&#38;#60;">
<!ENTITY gt     "&#62;">
<!ENTITY amp    "&#38;#38;">
<!ENTITY apos   "&#39;">
<!ENTITY quot   "&#34;">
0 голосов
/ 04 февраля 2012

Вам необходимо либо правильно закодировать его, либо поместить в раздел CDATA. Я бы порекомендовал первое.

...