2015-06-29 2 views
-4

Я читаю XML-файл и получаю ошибку ввода-вывода при чтении узла <kamerkant/>. Я использую следующее заявление для чтения узла:Ошибка ввода-вывода при чтении XML

Lclvalue := Sel.Selectnode('//Gordijn[1]/Kamerkant[1]/node()').nodeValue 

XML

<Gordijn> 
    <StofNaam>Aroma 211004</StofNaam> 
    <Kleur>211</Kleur> 
    <Gordijnsoort>streepgordijn</Gordijnsoort> 
    <Vertrek>Woonkamer voor</Vertrek> 
    <Kamerkant/> 
    <Hoogte>100.0</Hoogte> 
</Gordijn> 
+0

Что такое последний тег? он не закрывает один, он снова открывается! –

+0

К сожалению, последний тег: – user3552264

+2

Пожалуйста, имейте в виду, что мы понятия не имеем, что такое 'Sel'. –

ответ

3

Ну, что еще вы хотите, чтобы с такими данными и таким запросом?

С просьбой «// Gordijn [1]/Kamerkant [1]/узел () «вы буквально просите« все узлы с Kamerkant [1] »

Но ваш Kamerkant0 является пустым узлом - он содержит узлы ZERO внутри него. Таким образом, результат вашего запроса - извлечь узлы из контейнера без внутренних узлов - может быть только NULL или пустой набор, не имеющий ничего в нем. А что такое nodeValue ничего, из несуществующего объекта? Ошибочно пытаться получить что-то из ничего, не так ли?

Просто используйте один из XPath калькуляторов я упомянул, введите там свой образец XML и выполнить оценку для запросов

  • // Gordijn [1]/Kamerkant [1]/узел()
  • // Gordijn [1]/Kamerkant [1]
  • // Gordijn [1]/узел()

См разницу самостоятельно.

При этом, когда вы используете SQL - вам нужно отлаживать ваш запрос и данные в каком-то общем не-Delphi SQL-инструменте, и только после этого, когда вы получили правильный протестированный SQL-запрос, чтобы скопировать его в ваш код Delphi.
То же самое относится к XPath - вам лучше сначала использовать калькуляторы XPath для отладки запросов XPath за пределами Delphi, и только тогда, когда вам удастся заменить тестовый исправленный XPath на ваш код Delphi.


Согласно

вам, возможно (в зависимости от различных ур исходных данных) может использовать что-то вроде

Lclvalue := Sel.Selectnode('//Gordijn[1]/Kamerkant[1]'); 
    if LclValue.hasChildNodes then begin 
    LclNodes := LclValue.childNodes; 
    for i := 1 to LclNodes.length do begin 
     LclValue := LclNodes.item[i]; 
     ... process LclValue.... 
    end; 
    end; 
    LclValue := nil; // release memory you need no more 
    LclNodes := nil; 

Это не значит, что это действительно самый эффективный способ сделать это, он явно не вписывается в мировоззрение XPath на основе набора. Для меня это выглядит как «индексированный метод последовательного доступа», применяемый к SQL-источнику данных.

Так что мне кажется, что вам не нужно выбирать один узел, в частности, менее первый узел («[1]» в вашем запросе - почему ???).

Вы действительно пытаетесь получить список ВСЕХ узлов, которые могут быть вам интересны, и подготовиться к этому событию не будет.

Например, ошибка ввода-вывода, которую вы получаете, - МОЖЕТ (или может быть, я не знаю, проверьте документы), точно так же, как ваш синтаксический анализатор xml сообщает «ничего не найдено, пустые результаты».


открыть www.google.com и набираю там "StackOverflow чек XPATH, если узел пуст"

Тем не менее, существуют разные XPath и различные XPath-движки - так может ли синтаксический анализатор XML вашего кода использовать эти методы, которые вы можете определить.


Но по крайней мере следующее - не очень эффективное также - представляется возможным;

LclNodes := Sel.Selectnodes('//Gordijn/Kamerkant'); // all the Kamerkants 
    // MAYBE check for error if XML source has no single Kamerkant, 
    // i can only GUESS how that maybe would be represented 
    // you can CHECK it or READ DOCS 

    for i := 1 to LclNodes.length do begin 
    // i GUESS LclNodes.length=0 for no Kamerkants data input - i may be badly wrong 
    LclValue := LclNodes.item[i]; // some Kamerkant 
    if LclValue.hasChildNodes then begin 
     LclKamerkantNodes := LclValue.childNodes; 
     for j := 1 to LclKamerkantNodes.length do begin 
      LclValue := LclKamerkantNodes.item[j]; 
      ... process LclValue.... 
     end; 
    end; 
    end; 
    LclValue := nil; // release memory you need no more 
    LclKamerkantNodes := nil; 
    LclNodes := nil; 

В последнем коде я полагаю, что в отношении генерала XPath к SelctNode/SelectNodes такое же, как отношение SQL к сингулярной/общей операции выбора. Первый должен производить ровно 1 строку результата, менее 1 или более, чем 1 - условия ошибки. Последний дает вам набор строк, которые могут быть пустыми или могут быть множественными, а также единственными, поэтому у вас есть гибкость для кодирования этих случаев. Первый является лаконичным, но хрупким в отношении неожиданных входных данных. Последний гораздо более гибкий, но также гораздо более утомительный и многословный. Выбор определенно ваш. Но, судя по вашей путанице w.r.t I/O Error - ваш первоначальный выбор использовать hardcoded Single Select, возможно, был неудачным.

+0

Hi Arioch, Спасибо за ответ. Но как я могу проверить, не является ли узел незаполненным? – user3552264

+1

Это еще один вопрос, не так ли? И это даже не о Delphi и о XML/XPath вообще Для определенного вопроса, который вы задали, я думаю, вы получили ответ. Итак - возьмите себе свой любимый калькулятор XPath, откройте преподаватели/руководства, откройте Google - и поэкспериментируйте. PS: с вашим конкретным образцом - просто не вызывайте «.nodeValue» - получите некоторый результат и оцените, что это прежде. Я не знаю, какой тип вы получаете после Sel.Selectnode и какие свойства/методы у него есть, но я думаю, вы можете его проверить. –

+0

Я открываю www.google.com, и я печатаю там, где «stackoverflow xpath проверяет, является ли узел пустым» - два первых результата: http://stackoverflow.com/questions/15909348 и http://stackoverflow.com/questions/13703478/// это говорит о том, что существуют разные версии XPath и разные XPath-движки, поэтому может ли синтаксический анализатор вашего кода использовать эти методы только для определения. –

Смежные вопросы