Как я могу разобрать пространство имен с помощью SAX-парсера? - PullRequest
7 голосов
/ 14 августа 2010

Использование поискового URL в твиттере т.е.http://search.twitter.com/search.rss?q=android возвращает CSS с элементом, который выглядит следующим образом:

<item>
      <title>@UberTwiter still waiting for @ubertwitter  android app!!!</title>
      <link>http://twitter.com/meals69/statuses/21158076391</link>
      <description>still waiting for an app!!!</description>
      <pubDate>Sat, 14 Aug 2010 15:33:44 +0000</pubDate>
      <guid>http://twitter.com/meals69/statuses/21158076391</guid>
      <author>Some Twitter User</author>
      <media:content type="image/jpg" height="48" width="48" url="http://a1.twimg.com/profile_images/756343289/me2_normal.jpg"/>
      <google:image_link>http://a1.twimg.com/profile_images/756343289/me2_normal.jpg</google:image_link>
      <twitter:metadata>
        <twitter:result_type>recent</twitter:result_type>
</twitter:metadata>
</item>

Довольно просто.Мой код анализирует все (заголовок, ссылку, описание, pubDate и т. Д.) Без каких-либо проблем.Тем не менее, я получаю нулевое значение:

<google:image_link>

Я использую Java для анализа RSS-канала.Нужно ли обрабатывать составные локальные имена иначе, чем более простое локальное имя?

Это фрагмент кода, который анализирует Link, Description, pubDate и т. Д .:

@Override
    public void endElement(String uri, String localName, String name)
            throws SAXException {
        super.endElement(uri, localName, name);
        if (this.currentMessage != null){
            if (localName.equalsIgnoreCase(TITLE)){
                currentMessage.setTitle(builder.toString());
            } else if (localName.equalsIgnoreCase(LINK)){
                currentMessage.setLink(builder.toString());
            } else if (localName.equalsIgnoreCase(DESCRIPTION)){
                currentMessage.setDescription(builder.toString());
            } else if (localName.equalsIgnoreCase(PUB_DATE)){
                currentMessage.setDate(builder.toString());
            } else if (localName.equalsIgnoreCase(GUID)){
                currentMessage.setGuid(builder.toString());
            } else if (uri.equalsIgnoreCase(AVATAR)){
                currentMessage.setAvatar(builder.toString());
            } else if (localName.equalsIgnoreCase(ITEM)){
                messages.add(currentMessage);
            } 
            builder.setLength(0);   
        }
    }

startDocument выглядиткак:

@Override
    public void startDocument() throws SAXException {
        super.startDocument();
        messages = new ArrayList<Message>();
        builder = new StringBuilder();

    }

startElement выглядит так:

@Override
    public void startElement(String uri, String localName, String name,
            Attributes attributes) throws SAXException {
        super.startElement(uri, localName, name, attributes);
        if (localName.equalsIgnoreCase(ITEM)){
            this.currentMessage = new Message();
        } 
    }

Tony

Ответы [ 5 ]

1 голос
/ 15 августа 2010

Из примера на самом деле не ясно, к какому пространству имен привязывается префикс «google» - предыдущий ответ немного неверен в том смысле, что он НЕ находится в пространстве имен «google»; скорее это пространство имен, к которому привязывается префикс «google». Таким образом, вы должны соответствовать пространству имен (идентифицированному URI), а не префиксу. У SAX есть запутанный способ сообщения о локальных комбинациях имя / пространство имен-префикс, и это зависит от того, включена ли обработка пространства имен.

Вы также можете рассмотреть альтернативные библиотеки / API обработки XML; В то время как реализации SAX производительны, есть и более быстрые и более удобные альтернативы. Реализации Stax (javax.xml.stream. *), Такие как Woodstox (и даже стандартная реализация, в которую входит JDK 1.6), быстрые и немного более удобные. И StaxMate библиотека, построенная на основе Stax, намного проще в использовании как для чтения, так и для записи, и по скорости так же быстро, как реализации SAX, такие как Xerces. Кроме того, API Stax имеет меньше места для обработки пространства имен, поэтому легче увидеть, каково действительное пространство имен элементов.

1 голос
/ 14 августа 2010

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

Например, некоторые интерфейсы SAX1 в package org.xml.sax устарели, заменены аналогами SAX2, которые включают поддержку пространства имен (например, SAX1 Parser устарели и заменены на SAX2 XMLReader). Обратитесь к документации о том, как указать пространство имен uri или квалифицированное (с префиксом) qName.

Смотри также

0 голосов
/ 17 апреля 2011

Используя метод startPrefixMapping моего обработчика xml, я смог разобрать текст пространства имен.

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

GoogleReader xmlhandler = new GoogleReader();
xmlhandler.startPrefixMapping("dc", "http://purl.org/dc/elements/1.1/");

где dcэто пространство имен <dc:author>some text</dc:author>

0 голосов
/ 29 декабря 2010

Может помочь кому-нибудь, используя Android SAX util .Я пробовал geo: lat, чтобы получить элемент lat из пространства имен geo.

Пример XML:

<item> 
 <title>My Item title</title> 
 <geo:lat>40.720741</geo:lat> 
</item>

Первая попытка вернула ноль:

item.getChild("geo:lat");

Как указывалось выше, я обнаружил, что передача URI пространства имен в метод getChild работает.

item.getChild("http://www.w3.org/2003/01/geo/wgs84_pos#", "lat");
0 голосов
/ 15 августа 2010

Как сказал пользователь polygenelubricants: обычно синтаксический анализатор должен знать пространство имен для обработки элементов, которые принадлежат некоторому префиксному пространству имен. (Как этот <google:image_link> элемент.)

Это необходимо установить как «функцию синтаксического анализатора», которую AFAIK можно выполнить несколькими различными способами: Сам интерфейс XMLReader имеет метод setFeature(), который можно использовать для установки функций для определенного синтаксического анализатора, но вы также можете использовать тот же метод для класса SAXParserFactory, чтобы эта фабрика генерировала парсеры с уже включенными или выключенными этими функциями. Флаги стандартных функций SAX2 должны быть на веб-сайте SAXproject, но, по крайней мере, некоторые из них также перечислены в документации Java API пакета org.xml.sax .

Для простых документов вы можете попробовать воспользоваться ярлыком. Если вы на самом деле не заботитесь о пространствах имен и именах элементов, как в комбинации URL + локальное имя, и вы можете верить, что элементы, которые вы ищете (и только они), всегда имеют определенный префикс и что нет элементов из другие пространства имен с таким же локальным именем, тогда вы можете просто решить свою проблему, используя параметр qname метода startElement() вместо localName или наоборот, или добавив / отбросив префикс из строки имени тега, с которой вы сравниваете.

Содержимое параметров namespaceUri, qname или localName в соответствии со спецификациями Java фактически необязательно, и AFAIK может быть null по этой причине. Какие из них являются null, зависит от того, какие вышеупомянутые «функции синтаксического анализатора» влияют на пространства имен. Я не знаю, может ли параметр null варьироваться между элементами в пространстве имен и элементами без пространства имен - я не исследовал такое поведение.

PS. XML чувствителен к регистру. Поэтому в идеале вам не нужно игнорировать регистр при сравнении строк с именами тегов.
-Первая запись, ууу!

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