使用内联标记解析XHTML

时间:2010-04-16 15:19:14

标签: iphone xml cocoa nsxmlparser libxml2

我正在尝试在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>内容,到目前为止我的所有测试都已将其作为子元素提取出来,而我并不知道它在段落中的确切位置。

有人可以建议这样做吗?

感谢。

1 个答案:

答案 0 :(得分:1)

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

假设2.你想保持p内的任何元素完整。

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

使用Apple的示例代码设置NSXMLParser delegate。 您的代表需要使用ivar BOOL 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状态变量很重要的时候。解析器不会收到封闭的'&lt;'和'&gt;'元素的字符,因此您必须将elementName包装在'&lt;'中和'&gt;'字符并添加到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"])receivedData的内容添加到保存段落的NSMutableArray

- (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];
                         }
                 }
       }
}