iPhone SDK: загадка XML, после добавления дочернего узла forXPath ничего не возвращает (найдено хакерское решение)
У меня есть большая загадка здесь,
У меня есть свойство документа Gdataxml:
GDataXMLDocument *doc;
Я добавляю новый элемент в документ, интересно, что этот метод ниже выглядит идеально для других элементов, но не для элемента, который я только что добавил:
GDataXMLElement *newValueDefElement = [GDataXMLNode elementWithName:@"valuedefinition"];
[variableElement addChild:newValueDefElement];
и теперь, когда я запрашиваю:
NSString *path = [NSString stringWithFormat:@"//inferenceresponse/state/variable[pageId=%d]/valuedefinition",pageID];
NSArray *valueElement = [self.doc nodesForXPath:path error:nil];
Теперь массив поставляется с нулевыми объектами! новый добавленный элемент НЕ найден! но я могу видеть это в отладке как строку XML, как на земле он не может найти то, что я вижу это там в журнале? это проблема с кэшем, проблема с пространством имен или ошибка в GDataXML? еще раз... Проблема добавляет нового дочернего элемента, и он как-то не обновляется в документе, но я могу получить другие элементы в том же корне, если использовать тот же стандарт запроса Xpath
в NSlog я вижу, что новый элемент добавлен в документ.
NSData *xmlData2 = self.doc.XMLData;
NSString *s= [[[NSString alloc] initWithBytes:[xmlData2 bytes] length:[xmlData2 length] encoding:NSUTF8StringEncoding] autorelease];
NSLog(s);
Также Как self.doc.XMLData может дать что-то отличное от [self.doc nodeForXPath]? так что это дурачит меня, что мой документ в порядке, но, может быть, я повредил документ или неверное пространство имен при добавлении удаления некоторых элементов в предыдущем методе?
мой xml начинается так:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<inferenceresponse xmlns="">
<state goalreached="false">
..
..
Обновить
Я только что нашел (хакерское) решение; когда я конвертирую "doc" в NSData с помощью "doc.XMLData", а затем снова конвертирую обратно в doc, тогда это работает! но это не должно быть реальным решением, так как это плохо для преобразования, чтобы получить правильный объект документа. В чем здесь проблема? Я думаю, что это не может исправить пространства имен для нового ребенка.
1 ответ
Ваша проблема здесь:
<inferenceresponse xmlns="">
Атрибут пустого пространства имен явно сбивает с толку оценку XPath libxml. Если вы шагаете через GDataXMLNode nodesForXPath:namespaces:error:
, xmlXPathEval
действительно возвращает пустой набор узлов.
Если у вас есть контроль над генерацией XML, у меня есть правильные результаты XPath, удаляющие пустой атрибут.
<inferenceresponse>
Если изменение ответа сервера слишком сложно, вы можете отредактировать GDataXMLNode.m
: Найти метод fixQualifiedNamesForNode:graftingToTreeNode:
в реализации GDataXMLNode и заменить строку
if (foundNS != NULL) {
// we found a namespace, so fix the ns pointer and the local name
с
if (foundNS != NULL && foundNS->href != NULL && strlen((char *)foundNS->href) != 0) {
// we found a namespace, so fix the ns pointer and the local name