Come gestire l'elemento xml con CDATA e dati regolari usando SimpleXML

2

Sto facendo fatica a capire come posso deserializzare la seguente risposta da un feed RSS. Ho bisogno del testo blah blah blah ecc. Così come della sorgente di immagine incorporata http://host/path/to/picture.jpg .

<description>blah blah blah blah br /&gt;
<![CDATA[<img src=http://host/path/to/picture.jpg>]]>&lt;br /&gt;
blah blah blah blah&lt;br /&gt;&lt;br /&gt;
</description>

Ecco il mio modello di classe (o meglio quello che voglio che sia) - L'ho accorciato per brevità:

public static class Item {

    ...

    @Element(name="description", required=false)
    String descriptionContent;

    String imageLink;
    ...

}

Dai documenti so che posso impostare data=true sull'attributo @Element ma dalla mia lettura che funziona se l'intero contenuto del tuo elemento è CDATA, non parzialmente.

Sto usando questo su Android usando Retrofit e SimpleXMLConverter ma penso che sia proprio vicino.

    
posta piratemurray 21.07.2016 - 21:26
fonte

1 risposta

3

L'ho capito alla fine. Speriamo che questo aiuti gli altri in futuro.

Quello che serviva era un modo per interrompere il processo di deserializzazione ed eseguire un codice personalizzato per estrarre i dati. SimpleXML ti permette di usare molte strategie per serializzazione / deserializzazione. Ne ho scelto uno chiamato Strategia di annotazione in cui annoto la mia classe di modello POJO con l'annotazione @Convert che punta a una classe di convertitore.

....

@Element(name="description", required=false)
@Convert(DescriptionConverter.class)
Description description;

...

Ed ecco come appare il convertitore:

public class DescriptionConverter implements Converter<RssFeed.Description> {

    @Override
    public RssFeed.Description read(InputNode node) throws Exception {
        final String IMG_SRC_REG_EX = "<img src=([^>]+)>";
        final String HTML_TAG_REG_EX = "</?[^>]+>";

        String nodeText = node.getValue();

        Pattern imageLinkPattern = Pattern.compile(IMG_SRC_REG_EX);
        Matcher matcher = imageLinkPattern.matcher(nodeText);

        String link = null;
        while (matcher.find()) {
            link = matcher.group(1);
        }

        String text = nodeText.replaceFirst(IMG_SRC_REG_EX, "")
                              .replaceAll(HTML_TAG_REG_EX, "");

        return new RssFeed.Description(text, link);
    }

    @Override
    public void write(OutputNode node, RssFeed.Description value) throws Exception {
            ...
    }

}

Devi comunque dire a Simple di usare una strategia diversa, altrimenti ignorerà l'annotazione. Dato che sto usando Retrofit e SimpleXMLConverter ecco come appare la mia implementazione:

private static final Retrofit.Builder builder = new Retrofit.Builder()
            .baseUrl(API_BASE_URL)
            .addConverterFactory(SimpleXmlConverterFactory.create(new Persister(new AnnotationStrategy())));
    
risposta data 23.07.2016 - 14:30
fonte

Leggi altre domande sui tag