【问题标题】:Android SAX parser not getting full text from between tagsAndroid SAX 解析器没有从标签之间获取全文
【发布时间】:2011-02-19 18:05:13
【问题描述】:

我已经创建了自己的 DefaultHandler 来解析 rss 提要,并且对于大多数提要来说它工作正常,但是,对于 ESPN,由于 ESPN 格式化它的 url 的方式,它正在切断部分文章 url。来自 ESPN 的完整文章 URL 示例。

http://sports.espn.go.com/nba/news/story?id=5189101&campaign=rss&source=ESPNHeadlines

问题是由于某种原因 DefaultHandler 字符方法只能从包含上述 url 的标签中获取。

http://sports.espn.go.com/nba/news/story?id=5189101

如您所见,它从 & 转义码和之后的 URL 中删除了所有内容。如何让 SAX 解析器在这个转义码处不切断我的字符串?对于参考。这是我的字符方法..

 public void characters(char ch[], int start, int length) {

  String chars = (new String(ch).substring(start, start + length));

  try {
   // If not in item, then title/link refers to feed
   if (!inItem) {
    if (inTitle)
     currentFeed.title = chars;
   } else {
    if (inLink)
     currentArticle.url = new URL(chars);
    if (inTitle)
     currentArticle.title = chars;
    if (inDescription)
     currentArticle.description = chars;
    if (inPubDate)
     currentArticle.pubDate = chars;
    if (inEnclosure) {
    }
   }
  } catch (MalformedURLException e) {
   Log.e("RSSReader", e.toString());
  }
 }

罗伯·W.

【问题讨论】:

    标签: android parsing escaping sax


    【解决方案1】:

    如您所见,它正在切割 网址中的所有内容 &符号转义码及之后。

    来自characters()方法的documentation:

    解析器会调用这个方法来 报告每一块字符数据。 SAX 解析器可能返回所有连续的 单个块中的字符数据,或 他们可能会将其分成几块; 但是,任何字符中的所有字符 单个事件必须来自同一个 外部实体,以便定位器 提供有用的信息。

    当我编写 SAX 解析器时,我使用 StringBuilder 来附加传递给 characters() 的所有内容:

    public void characters (char ch[], int start, int length) {
        if (buf!=null) {
            for (int i=start; i<start+length; i++) {
                buf.append(ch[i]);
            }
        }
    }
    

    然后在endElement() 中,我获取StringBuilder 的内容并对其进行处理。这样,如果解析器多次调用characters(),我不会错过任何东西。

    【讨论】:

    • 好吧,我并没有真正花时间完全理解解析器是如何工作的。阅读您的答案后,我回去进一步研究以获得更好的理解。你的建议当然是问题所在,我已经更新了我的代码以正确处理 char 数据。 TY
    • @CommonsWare:会漏掉一些字符吗?在我的情况下,我正面临它。
    • 我的 xml 中有 image1:title 有时我得到了全部价值,有时我只有“itle”或“Title”。我曾尝试打印值,但它从未为部分值打印“image1:”。
    • @Ankit:请打开一个新的 StackOverflow 问题,显示您的输入、解析代码和结果。
    • @KK_07k11A0585:这是一个单独的 XML 元素。在解析时,您已经在 startElement() 和 endElement() 方法中得到它。
    【解决方案2】:
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        // TODO Auto-generated method stub
        sb=new StringBuilder();
        if(localName.equals("icon"))
        {
            iconflag=true;
        }
    }
    
    @Override
    public void characters (char ch[], int start, int length) {
        if (sb!=null && iconflag == true) {
            for (int i=start; i<start+length; i++) {
                sb.append(ch[i]);
            }
        }
    }
    
    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        // TODO Auto-generated method stub
        if(iconflag)
        {
            info.setIcon(sb.toString().trim());
            iconflag=false;
        }
    }
    

    所以我想通了,上面的代码就是解决方案。

    【讨论】:

      【解决方案3】:

      前几天我遇到了这个问题,原来这是因为字符方法被多次调用,以防这些字符中的任何一个包含在值中:

      "   &quot;
      '   &apos;
      <   &lt;
      >   &gt;
      &   &amp;
      

      还要小心值内的换行符/换行符!!! 如果 xml 在没有您控制的情况下被换行,则还将为语句中的每一行调用 characters 方法,并且它将返回换行符! (您需要依次手动剥离)。

      处理所有这些问题的示例处理程序是这个:

       DefaultHandler handler = new DefaultHandler() {
         private boolean isInANameTag = false;
         private String localname;
         private StringBuilder elementContent;
      
         @Override
         public void startElement(String uri, String localName,String qName, Attributes attributes) throws SAXException {
          if (qname.equalsIgnoreCase("myfield")) {
            isInMyTag = true;
            this.localname = localname;
            this.elementContent = new StringBuilder();
          }
         }
      
         public void characters(char[] buffer, int start, int length) {
            if (isInMyTag) {
               String content = new String(ch, start, length);
               if (StringUtils.equals(content.substring(0, 1), "\n")) {
                    // remove leading newline
                    elementContent.append(content.substring(1));
               } else {
                    elementContent.append(content);
               }
            }
         }
      
         public void endElement(String uri, String localName, String qName) throws SAXException {
           if (qname.equalsIgnoreCase("myfield")) {
             isInMyTag = false;
             // do something with elementContent.toString());
             System.out.println(elementContent.toString());
             this.localname = "";
           }
         }
      }
      

      我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2018-01-24
        • 2012-07-22
        • 2012-05-09
        • 2016-11-09
        • 1970-01-01
        • 2021-12-14
        • 2012-06-01
        • 1970-01-01
        相关资源
        最近更新 更多