SaxParser 无法解析 url

SaxParser is failing to parse url's

我正在尝试使用 SaxParser 解析 xml,但有时无法解析来自 xml 提要的 url。我 xml 喂过这样的东西。

<songs>
  <song id="269611">
    <start>2015-01-02T04:36:52Z</start>
    <title>Beyond Me</title>
    <artist>tobyMac</artist>
    <logo>http://www.quuit.com/quu/content/themes/base/images/music_none.png</logo>
    <lyrics>no</lyrics>
    <bio>yes</bio>
    <coupon>no</coupon>
    <ad>no</ad>
  </song>
  <song id="77476">
    <start>2015-01-2T04:32:51Z</start>
    <title>WHOLLY YOURS</title>
    <artist>David Crowder Band</artist>
    <logo>http://www.quuit.com/imageserver/thumbnail/WHOLLY_YOURSDavid_Crowder_Band.jpeg</logo>
    <lyrics>no</lyrics>
    <bio>yes</bio>
    <coupon>no</coupon>
    <ad>no</ad>
  </song>
</songs>

当我尝试解析上述内容时,有时徽标标记中的 url 会被截断。而不是 http://www.quuit.com/imageserver/thumbnail/WHOLLY_YOURSDavid_Crowder_Band.jpeg 这个 url,我只是得到 Band.jpeg 或 wder_Band.jpeg 等,有时它会给出完整的 url,这很好。这个问题是随机发生的,看起来很奇怪。有人请帮助我。

这是我为解析上述内容而编写的代码 xml:

public class QuuAsyncTask extends AsyncTask<Object, Void, BaseQuuVO> {

private Exception exception;
private QuuServiceDelegate serviceDelegate;

protected BaseQuuVO doInBackground(Object... param) {
    BaseQuuVO baseVO = new BaseQuuVO();

    try {
        QuuDefaultHandler defaultHandler = (QuuDefaultHandler) param[1];
        serviceDelegate = (QuuServiceDelegate) param[2];
        /** Handling XML */
        SAXParserFactory spf = SAXParserFactory.newInstance();
        SAXParser sp = spf.newSAXParser();
        XMLReader xr = sp.getXMLReader();

        /** Send URL to parse XML Tags */
        URL sourceUrl = new URL((String) param[0]);

        /** Create handler to handle XML Tags ( extends DefaultHandler ) */
        xr.setContentHandler(defaultHandler);
        InputSource inputSource = new InputSource(sourceUrl.openStream());
        inputSource.setEncoding("ISO-8859-1");
        xr.parse(inputSource);
        baseVO = (BaseQuuVO) defaultHandler.getData();
        return baseVO;
    } catch (Exception e) {
        this.exception = e;
        return null;
    }
}

protected void onPostExecute(BaseQuuVO result) {
    super.onPostExecute(result);
    // TODO: check this.exception
    // TODO: do something with the feed
    if (result != null) {
        serviceDelegate.quuResponseReceived(result);
    } else {
        serviceDelegate.quuResponseFailure("Problem loading data");
    }

}

public class QuuAsyncTask extends AsyncTask<Object, Void, BaseQuuVO> {

    private Exception exception;
    private QuuServiceDelegate serviceDelegate;

    protected BaseQuuVO doInBackground(Object... param) {
        BaseQuuVO baseVO = new BaseQuuVO();

        try {
            QuuDefaultHandler defaultHandler = (QuuDefaultHandler) param[1];
            serviceDelegate = (QuuServiceDelegate) param[2];
            /** Handling XML */
            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();
            XMLReader xr = sp.getXMLReader();

            /** Send URL to parse XML Tags */
            URL sourceUrl = new URL((String) param[0]);

            /** Create handler to handle XML Tags ( extends DefaultHandler ) */
            xr.setContentHandler(defaultHandler);
            InputSource inputSource = new InputSource(sourceUrl.openStream());
            inputSource.setEncoding("ISO-8859-1");
            xr.parse(inputSource);
            baseVO = (BaseQuuVO) defaultHandler.getData();
            return baseVO;
        } catch (Exception e) {
            this.exception = e;
            return null;
        }
    }

    protected void onPostExecute(BaseQuuVO result) {
        super.onPostExecute(result);
        // TODO: check this.exception
        // TODO: do something with the feed
        if (result != null) {
            serviceDelegate.quuResponseReceived(result);
        } else {
            serviceDelegate.quuResponseFailure("Problem loading data");
        }

    }
}

public class PlayListXMLParser extends QuuDefaultHandler {

    private List<PlayListSongVO> songsVO;
    private String tempVal;
    private PlayListSongVO tempPlayListSongVO;
    private PlayListsVO playListsVO = new PlayListsVO();

    public PlayListXMLParser() {
        songsVO = new ArrayList<PlayListSongVO>();
    }

    @Override
    public PlayListsVO getData() {
        playListsVO.setSongs(songsVO);
        return playListsVO;
    }

    // Event Handlers
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes) throws SAXException {
        // reset
        tempVal = "";
        if (qName.equalsIgnoreCase("song")) {
            // create a new instance of employee
            tempPlayListSongVO = new PlayListSongVO();
        }
    }

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

    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if (qName.equalsIgnoreCase("song")) {
            // add it to the list
            songsVO.add(tempPlayListSongVO);
        } else if (qName.equalsIgnoreCase("id")) {
            tempPlayListSongVO.setId(tempVal);
        } else if (qName.equalsIgnoreCase("start")) {
            tempPlayListSongVO.setStart(tempVal);
        } else if (qName.equalsIgnoreCase("title")) {
            tempPlayListSongVO.setTitle(tempVal);
        } else if (qName.equalsIgnoreCase("artist")) {
            tempPlayListSongVO.setArtist(tempVal);
        } else if (qName.equalsIgnoreCase("logo")) {
            tempPlayListSongVO.setLogo(tempVal);
        } else if (qName.equalsIgnoreCase("lyrics")) {
            tempPlayListSongVO.setLyrics(tempVal);
        } else if (qName.equalsIgnoreCase("bio")) {
            tempPlayListSongVO.setBio(tempVal);
        } else if (qName.equalsIgnoreCase("coupon")) {
            tempPlayListSongVO.setCoupon(tempVal);
        } else if (qName.equalsIgnoreCase("ad")) {
            tempPlayListSongVO.setAd(tempVal);
        }

    }
}

更新:

public class SongDetailXMLParser extends QuuDefaultHandler {

    // private String tempVal;
    private SongDetailsVO songDetailsVO;
    private StringBuilder tempStringBuilder;

    public SongDetailXMLParser() {

    }

    @Override
    public SongDetailsVO getData() {
        return songDetailsVO;
    }

    // Event Handlers
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes) throws SAXException {
        tempStringBuilder = new StringBuilder();
        if (qName.equalsIgnoreCase("song")) {
            // create a new instance
            songDetailsVO = new SongDetailsVO();
        }
    }

    public void characters(char[] ch, int start, int length)
            throws SAXException {
        tempStringBuilder.append(ch);

    }

    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        if (qName.equalsIgnoreCase("song")) {
            // add it to the list

        } else if (qName.equalsIgnoreCase("id")) {
            songDetailsVO.setId(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("duration")) {
            songDetailsVO.setDuration(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("title")) {
            songDetailsVO.setTitle(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("artist")) {
            songDetailsVO.setArtist(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("logo")) {
            songDetailsVO.setLogo(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("amazon")) {
            songDetailsVO.setAmazon(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("itunes")) {
            songDetailsVO.setItunes(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("videolink")) {
            songDetailsVO.setVideolink(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("ringtone")) {
            songDetailsVO.setRingtone(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("lyrics")) {
            songDetailsVO.setLyrics(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("bio")) {
            songDetailsVO.setBio(tempStringBuilder.toString());
        } else if (qName.equalsIgnoreCase("share")) {
            songDetailsVO.setShare(tempStringBuilder.toString());
        }
    }
}

XML 解析器被允许以任何它喜欢的方式分解文本节点,并在对 characters() 方法的多次调用中提供它们。您的 characters() 方法不允许这样做:

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

如果多次调用,tempVal 将仅包含最近一次调用的结果。

要收集所有文本信息,您可以使用以下方法:

public void characters(char[] ch, int start, int length)
    throws SAXException {
    tempStringBuilder.append(ch, start, length);

}

假设您在别处将 tempStringBuilder 变量定义为 StringBuilderStringBuffer

让我们来看看 documentation :

void characters(char[] ch, int start, int length) throws SAXException

The Parser will call this method to report each chunk of character data. SAX parsers may return all contiguous character data in a single chunk, or they may split it into several chunks

The application must not attempt to read from the array outside of the specified range.

所以上面的代码是非常错误的:

public void characters(char[] ch, int start, int length)
        throws SAXException {
    tempStringBuilder.append(ch);
}

当您为每个块重新创建 String 时,这个也是:

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

试试这个:

public void characters(char[] ch, int start, int length)
        throws SAXException {
    tempStringBuilder.append(ch, start, length);
}