0

我正在尝试在 iPhone 上使用 TBXML 解析 XHTML 文档(尽管如果更容易的话,我很乐意使用 libxml2 或 NSXMLParser)。我需要将正文的内容提取为一系列段落并维护内联标签,例如:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
       <title>Title</title>
       <link rel="stylesheet" href="css/style.css" type="text/css"/>
       <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8"/>
    </head>
    <body>
       <div class="body">
          <div>
             <h3>Title</h3>
             <p>Paragraph with <em>inline</em> tags</p>
             <img src="image.png" />
          </div>
       </div>
    </body>
</html>

我需要提取段落,但保留段落的<em>inline</em>内容,到目前为止,我的所有测试都将其提取为子元素,而我并不知道它在段落中的确切位置。

谁能建议一种方法来做到这一点?

谢谢。

4

1 回答 1

1

假设 1. 您只对 p(段落)元素中的数据感兴趣并且您正在使用 NSXMLParser。

假设 2。您希望保持 p 内的任何元素完好无损。

您要使用的策略是为您的解析器创建一个状态机,以便它知道何时需要保存数据以及何时忽略接收到的数据。

NSXMLParser delegate使用 Apple 的示例代码进行设置。您的委托将需要一个 ivarBOOL inParagraph来跟踪何时保留或丢弃数据。inParagaph的初始值为NO。当您的代表收到parser:didStartElement:namespaceURI:qualifiedName:attributes:消息时,if ([element isEqual:@"p"])清除您的receivedData变量并设置inParagraph = YES

编辑: receivedData 是一个 NSMutableString。修复了代码示例

此时您parser delegate要保存收到的数据。

parser delegate收到parser:foundCharacters:消息时,将字符串附加到receivedData示例代码中。

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if (inParagraph) [receivedData appendString:string];
}

当解析器遇到内联元素时,委托将parser:didStartElement:namespaceURI:qualifiedName:attributes:再次接收。这是inParagraph状态变量很重要的时候。解析器不会接收元素的封闭 '<' 和 '>' 字符,因此您必须将elementName'<' 和 '>' 字符包装起来并添加到receivedData. 就像是

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{ if (inParagraph) 
    {
        NSString *inlineElementName = [NSString stringWithFormat:@"<%@>", elementName];
        [receivedData appendString:inlineElementName];
    }
....
}

parser delegate收到parser:didEndElement:namespaceURI:qualifiedName:消息时,它会检查它是否在“p”元素中if (inParagraph && ![elementName isEqual:@"p"],关闭内联元素。if ([elementName isEqual:@"p"])将 的内容添加receivedDataNSMutableArray您的段落中。

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
   if (inParagraph)
        {
             if (![elementName isEqual:@"p"])
                 { 
                      NSString *inlineElementName = [NSString stringWithFormat:@"</%@>", elementName];
                     [receivedData appendString:inlineElementName];             
                 } else { // received closing </p> tag add receivedData to the paragraph array
                          [paragraphsArray addObject:[receivedData copy]];
                          [self setInParagraph:NO];
                         }
                 }
       }
}
于 2010-04-17T01:59:00.380 回答