Текст узла XML вызывает проблемы, когда он содержит забавные символы - PullRequest
0 голосов
/ 11 декабря 2011

Я устанавливаю символы внутри элемента xml в следующем событии:

 public void characters(char[] ch, int start, int length) {
        elementText = new String(ch, start, length);
    }

Где elementText - это строка.

<client-key>#&lt;ABC::DEF::GHI:0x102548f78&gt;</client-key>

Я загружаю эти xml-данные в объекты Java, и свойство моих объектов имеет следующее значение:

 '\n        '

Теперь, если я изменю текст в элементе <client-key> выше, он отлично подходит для моего свойства объектов.

Есть ли какая-то проблема с кодировкой, которую мне нужно как-то решить?

public void endElement(String uri, String localName, String qName) {

       if (qName.equals("client-key")) {
            client.setClientKey(elementText);
        }

}

Ответы [ 3 ]

11 голосов
/ 25 декабря 2011

Это, вероятно, то, что вы получили бы, если бы ваш XML был приведен в порядок:

<client-key>
    #&lt;ABC::DEF::GHI:0x102548f78&gt;
</client-key>

См. ContentHandler

символов
...
Парсер вызовет этот метод, чтобы сообщить о каждом фрагменте символьных данных. Парсеры SAX могут возвращать все смежные символьные данные в одном фрагменте, , или они могут разбивать их на несколько фрагментов ; ...

Вам лучше использовать что-то вроде:

public void characters(char[] ch, int start, int length) {
  // Note the +=
  elementText += new String(ch, start, length);
}

public void endElement(String uri, String localName, String qName) {

  if (qName.equals("client-key")) {
    client.setClientKey(elementText);
  }
  elementText = "";
}
2 голосов
/ 30 декабря 2011

Анализатор XML обычно использует два этапа для обработки данных в документе.На первом этапе документ (который представляет собой последовательность байтов) декодируется в последовательность символов, которые помещаются во входной буфер.Фактический синтаксический анализ XML выполняется на втором этапе, на котором анализируются различные конструкции, такие как начальный и конечный теги элемента.Обратите внимание, что оба этапа выполняются параллельно.Точнее, входной буфер пополняется по требованию в процессе синтаксического анализа XML.Также обратите внимание, что если документ уже представлен в виде последовательности символов (например, с использованием StringReader), то декодирование на первом этапе пропускается, но синтаксический анализатор все равно будет использовать входной буфер для хранения символов, считанных из потока.

Как отмечали другие, синтаксический анализатор SAX не обязан сообщать о текстовом узле как об одном фрагменте.Он может по своему усмотрению принять решение разделить узел на несколько частей.Это называется не-объединяющим синтаксическим анализом .

То, что вы называете «забавными символами», на самом деле являются ссылками на сущности символов (<и> в вашем случае).Они должны быть расшифрованы (в вашем случае «<» и «>») перед отправкой данных в приложение.Однако это можно сделать только на втором этапе.Причина в том, что та же последовательность символов (например, «<») может не нуждаться в декодировании, если она появляется в другом контексте, в частности в разделе CDATA. </p>

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

С другой стороны, если текстЕсли узел содержит ссылки на сущности, то синтаксический анализатор не может передать данные непосредственно из входного буфера в приложение, поскольку часть данных нуждается в дальнейшем декодировании.Чтобы избежать многократного копирования данных, большинство анализаторов предпочитают передавать части, которые не нуждаются в дальнейшем декодировании, непосредственно в приложение, в то время как ссылки на сущности сначала декодируются в отдельный буфер.Вот почему вы получаете фрагменты, которые в исходном документе разделены ссылками на сущности.

0 голосов
/ 30 декабря 2011

Работает нормально.Но, по его словам, содержимое узла состоит из нескольких частей.Так что вам нужно добавить его.В приведенном ниже примере показан вывод с использованием и без использования cdata

public class XMLTest {

    public static void main(String argv[]) {
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser saxParser = factory.newSAXParser();

            DefaultHandler handler = new DefaultHandler() {

                public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
                }

                public void endElement(String uri, String localName, String qName) throws SAXException {
                }

                public void characters(char ch[], int start, int length) throws SAXException {
                    System.out.println(new String(ch, start, length));
                }
            };
            saxParser.parse("test.xml", handler);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

<?xml version="1.0"?>
<company>
    <staff>
        <client-key>#&lt;ABC::DEF::GHI:0x102548f78&gt;</client-key>    
        <client-key><![CDATA[#<ABC::DEF::GHI:0x102548f78>]]></client-key>    
    </staff>
</company>

Вывод:

#
<
ABC::DEF::GHI:0x102548f78
>


#<ABC::DEF::GHI:0x102548f78> 

Последний полученный вами блок для первого тега ключа клиента - это новыйсимвол строки с некоторыми пробелами.Так как вы не добавляете его, вы получаете символ новой строки только с некоторыми пробелами, которые являются последним фрагментом.

Это прекрасно работает, если у вас есть нормальный символ, потому что в содержимом нет разрыва, и вы можете получить его водин блок.

тот же вход:

<client-key>testing</client-key>

выход:

testing

Так что вы либо используете CDATA, либо добавляете.

...