xpaths和xml迭代

时间:2012-02-22 15:57:02

标签: objective-c ios xml xpath

我有一个像这样的xml:

    <root>
   ...
    <images xmlns:a="http://.../Arrays">
        <a:string>http://images...233/Detail.jpg</a:string>
        <a:string>http://images....233/Detail2.jpg</a:string>
    </images>
   ...
   <images xmlns:a="http://.../Arrays">
        <a:string>http://images...233/Detail3.jpg</a:string>
        <a:string>http://images....233/Detail4.jpg</a:string>
        <a:string>http://images....233/Detail5.jpg</a:string>
    </images>
....
<images xmlns:a="http://.../Arrays">
        <a:string>http://images...233/Detail6.jpg</a:string>
        <a:string>http://images....233/Detail7.jpg</a:string>
    </images>
   ....
<root>

如何迭代将所有图像放入NSArray?

2 个答案:

答案 0 :(得分:0)

  

如何迭代将所有图像放入NSArray?

我不知道你的意思是NSArray

通常,XPath引擎公开类似SelectNodes(string XpathExpression)的方法,可能包含NamespaceManager对象 - 参数的重载。

此方法通常返回一个XmlNodelist对象,该对象包含所有结果并允许迭代它们。

一个XPath表达式,用于选择所提供的XML文档中包含图像的所有文本节点

<images xmlns:a="http://.../Arrays">
    <a:string>http://images...233/Detail.jpg</a:string>
    <a:string>http://images....233/Detail2.jpg</a:string>
</images>

<强>是

/*/*/text()

这将选择其父项是XML文档中top元素的子项的任何文本节点 - 在这种情况下,此类节点正好是具有字符串值的两个文本节点:

"http://images...233/Detail.jpg"

"http://images....233/Detail2.jpg"

答案 1 :(得分:0)

要在iOS设备上执行此操作,您最好使用为您实施XPath评估的第三方C库,因为为iOS提供的内置XML支持不会。您最好的选择是使用libxslt,但由于libxslt的可下载版本以动态库的形式出现,因此无法直接在iOS上使用。相反,您需要下载libxslt的源代码并将其直接构建到您的应用程序中。有关让libxslt在iOS上运行的更多信息,请参阅this SO post

一旦libxslt在你的项目中工作,你可以使用C代码来解析XML并评估任意XPath表达式,如“/ / / text()”,正如@Dmitre所建议的那样Novatchev。关于如何做到这一点有很多变种,但这样的例子给你一个例子:

CFArrayRef findImages(CFStringRef filename) {

    xmlInitParser();
    LIBXML_TEST_VERSION

    // Parse XML template document into DOM tree
    CFIndex filenameLength = CFStringGetLength(filePath);
    char *fileNameCString = (char *) calloc(filenameLength + 1, sizeof(char));
    CFStringGetCString(filePath, fileNameCString, filenameLength + 1, kCFStringEncodingUTF8);

    xmlDocPtr doc = xmlReadFile(fileNameCString, NULL, 0);
    if (doc == NULL) 
    {
        // Error - File not readable
        free(fileNameCString);
        return nil;
    }
    else
    {
        free(fileNameCString);
        xmlCleanupParser();
    }

    /* Create xpath evaluation context */
    xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
    if(xpathCtx == NULL) 
    {
        // Error - Failed to create Xpath context
        return NULL;
    }


    /* Evaluate xpath expression */
    char *xpathCString = "/*/*/text()";
    xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(BAD_CAST xpathCString, xpathCtx);
    if(xpathObj == NULL) 
    {
        // Error - Failed to evaluate XPath
        xmlXPathFreeContext(xpathCtx); 
        return NULL;
    }
    xmlNodeSetPtr resultNodes = xpathObj->nodesetval;


    // You'll want to double-check the following part: I don't have sample code for
    // this so I can't be certain this is 100% correct, but it gets the idea across!

    CFMutableArrayRef result = CFArrayCreate(kCFAllocatorDefault, 0, NULL);
    for (int i = 0; i < resultNodes->nodeNr; i++) {
        char *imageCString = xmlNodeGetContent(resultNodes->nodeTab[i]);
        CFStringRef imageString = CFStringCreateWithCString(kCFAllocatorDefault, imageCString, kCFStringEncodingUTF8);
        CFArrayAppendValue(result, imageString);
    }

    return result;
}

我已根据我用于评估XPath表达式的一些工作示例代码将此代码示例放在一起,但是我将它组装成数组的最终部分是我的头脑:它可能无法完全正常工作!

请注意,此函数采用CFString作为XML文件的文件名,并返回结果的CFArray。这些类型与Objective-C NSString和NSArray类型“免费桥接”。这意味着您可以使用您习惯使用的“普通”类型从objective-C调用它们,并且我将在我提供的C代码中正确理解它们。