Android SAX 解析器没有从标签之间获取全文

Posted

技术标签:

【中文标题】Android SAX 解析器没有从标签之间获取全文【英文标题】:Android SAX parser not getting full text from between tags 【发布时间】: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("Rs-s-reader", e.toString());
  
 

罗伯·W.

【问题讨论】:

【参考方案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:请打开一个新的 *** 问题,显示您的输入、解析代码和结果。 @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 = "";
     
   

我希望这会有所帮助。

【讨论】:

以上是关于Android SAX 解析器没有从标签之间获取全文的主要内容,如果未能解决你的问题,请参考以下文章

xml 使用 sax 解析器从子标签解析数据

Android SAX XML Parser Access Enclosure 标签 URL 属性

使用 SAX 解析器解析自关闭 XML 标记时遇到问题

SAX 解析器从 endelement 获取属性

在 SAX 解析器中删除空格

解析具有相同父子标签的 XML,然后最好使用 SAX 解析器将父标签的值链接到子标签