Страница 1 из 1

Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 16:44
VBTerminator
Почему не работает следующий код?
Код: Выделить всё
    xmlDoc.async = False
    xmlDoc.validateOnParse = False
   
    xmlDoc.Load (App.Path & "\weather_input.xml")
    xmlDoc.setProperty "SelectionLanguage", "XPath"
   
    MsgBox xmlDoc.selectSingleNode("//tbody[@class='near']").selectSingleNode("tr[@class='t2']"). _     selectSingleNode("th[@class='date']").selectSingleNode("th[@class='date']").selectSingleNode("b").Text


Проблемы возникли на последней строке. Пишет, что "Object variable or With block variable not set".

Интересующий меня отрывок из XML-документа:
Код: Выделить всё
<?xml version="1.0" encoding="utf-8"?>
...
<tbody class="near">
            <tr class="t2 ">
                <th rowspan="4"><i>пн</i></th>
            </tr>
</tbody>

Re: Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 16:50
RayShade
Код потому что кривой :) Если б ты начал писать нормальный запрос, не состоящий из кучи вложенных вызовов, а сделал как я написал, то заметил бы что:
1. У тебя лишний элемент пути th[@class='date']
2. В документе нет tr[@class='t2'], а есть tr[@class='t2 ']

Код: Выделить всё
MsgBox xmlDoc.selectSingleNode("//tbody[@class='near']/tr[@class='t2']/th[@class='date']/b").text


С учетом как я погляжу, последних изменений в посте:

Код: Выделить всё
MsgBox xmlDoc.selectSingleNode("//tbody[@class='near']/tr[@class='t2']/th[@rowspan=4]/i").text


Да, я намеренно убрал последний пробел после t2, потому что это не кошерно, такие атрибуты заводить.

Re: Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 16:57
VBTerminator
RayShade писал(а):Да, я намеренно убрал последний пробел после t2, потому что это не кошерно, такие атрибуты заводить.

Это не я, а разработчики служб Яндекса.

Re: Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 17:01
RayShade
Вот дятлы :) Ну тогда, поставь там пробел в коде -- просто он играет большую роль так сказать :) Хотя, могу предложить вариант, которому будет пофиг на пробелы:
Код: Выделить всё
MsgBox xmlDoc.selectSingleNode("//tbody[normalize-space(@class)='near']/tr[normalize-space(@class)='t2']/th[normalize-space(@class)='date']/b").text

Re: Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 17:16
VBTerminator
Увы, не помогло. Привожу полные варианты модуля с кодом и XML-файла:
Код: Выделить всё
Option Explicit
Dim xmlDoc As New MSXML2.DOMDocument30
Dim xmlWeatherNode As MSXML2.IXMLDOMElement
Dim xmlCurrenrNode As MSXML2.IXMLDOMElement

Public Sub GetWeatherData()
    Dim strGettingData As String

    strGettingData = frmMain.inetYandexControl.OpenURL("http://weather.yandex.ru/27890/details/")
    If strGettingData = "" Then AddLog "! Ñòðàíèöà äàííûõ ïîãîäû íåäîñòóïíà!": Exit Sub
   
    Open App.Path & "\weather_input.xml" For Output As #10
    Print #10, strGettingData
    Close #10
   
    xmlDoc.async = False
    xmlDoc.validateOnParse = False
   
    xmlDoc.Load (App.Path & "\weather_input.xml")
    xmlDoc.setProperty "SelectionLanguage", "XPath"
   
    MsgBox xmlDoc.selectSingleNode("//tbody[normalize-space(@class)='near']/tr[normalize-space(@class)='t2']/th[normalize-space(@class)='date']/b").Text
End Sub

Re: Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 17:36
RayShade
Гы. Я не знаю, почему так, но короче я добавил ко всем тегам имя неймспейса и у меня все вышло :)
Код: Выделить всё
//default:tbody[normalize-space(@class)='near']/default:tr[normalize-space(@class)='t2']/default:th[normalize-space(@class)='date']/default:b

Re: Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 17:44
VBTerminator
RayShade писал(а):имя неймспейса

Имя чего?

Re: Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 18:17
RayShade
Namespace prefix :) default:tbody -- здесь default это namespace, а tbody - имя тега.

Re: Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 18:27
VBTerminator
RayShade писал(а):Namespace prefix :) default:tbody -- здесь default это namespace, а tbody - имя тега.

А как это оформлять в xml-файле? Как атрибут "namespace="default"" у тэга, или как?

Re: Почему не работает код?

СообщениеДобавлено: 06.04.2009 (Пн) 18:33
RayShade
А в XML это не надо никак оформлять :) Тут просто XML такой, что парсер к нему запросы без указания этого префикса не принимает :) Я хз отчего это.

Re: Почему не работает код?

СообщениеДобавлено: 07.04.2009 (Вт) 7:50
VBTerminator
Ха! "А в XML это не надо никак оформлять..."
Заменил "ошибочный" запрос на твой, xml-файл даже и не трогал, и получил в лицо:
Microsoft Visual Basic писал(а):Ссылка на необъявленный префикс пространства имён: "default".

Re: Почему не работает код?

СообщениеДобавлено: 07.04.2009 (Вт) 9:31
RayShade
Ха ха. Я вчера вот пользовался java имплементацией парсера/валидатора -- там все окей, в смысле что и документ грузится и выборка идет. А сейчас вот гружу это дело в MSXML2.DOMDocument, так ощибок никаких нет, но и DOM модель вся пустая :)

Re: Почему не работает код?

СообщениеДобавлено: 07.04.2009 (Вт) 10:52
VBTerminator
Ладно, хотел облегчить себе жизнь...
Придётся вручную парсить документ и выбирать значения.

Re: Почему не работает код?

СообщениеДобавлено: 07.04.2009 (Вт) 10:53
RayShade
Проблема в том что парсер неадекватно реагирует на DOCTYPE. Надо найти счас способ это дело обойти.

Re: Почему не работает код?

СообщениеДобавлено: 07.04.2009 (Вт) 11:26
VBTerminator
Перед записью в файл вставил следующий код:
Код: Выделить всё
Replace strGettingData, Replace("<!DOCTYPE html PUBLIC |-//W3C//DTD XHTML 1.0 Transitional//EN| |http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd|>", "|", Chr(34)), ""

Не помогло.

Re: Почему не работает код?

СообщениеДобавлено: 07.04.2009 (Вт) 11:37
RayShade
Чего-то странный replace какой-то. Почему просто не убить эту строку чем-то типа regxp вот такого вида \<!DOCTYPE.+?\>

Re: Почему не работает код?

СообщениеДобавлено: 07.04.2009 (Вт) 12:02
VBTerminator
Заинтриговало...
Синтаксис опиши, пожалуйста.

Re: Почему не работает код?

СообщениеДобавлено: 07.04.2009 (Вт) 12:10
RayShade
Код: Выделить всё
Function ReplaceTest(patrn, searchStr, replStr)
  Dim regEx as Object
  Set regEx = New RegExp
  regEx.Pattern = patrn
  regEx.IgnoreCase = True
  ReplaceTest = regEx.Replace(searchStr, replStr)
End Function


Ну и вызов будет примерно такой

Код: Выделить всё
ReplaceTest "\<!DOCTYPE.+?\>", strGettingData, ""


А, ну и RegExp чтоб создавать надо наверняка там референс какой-то подключить к проекту. А может и нет -- я не помню :)

Re: Почему не работает код?

СообщениеДобавлено: 07.04.2009 (Вт) 12:53
VBTerminator
RayShade писал(а):А, ну и RegExp чтоб создавать надо наверняка там референс какой-то подключить к проекту. А может и нет -- я не помню :)

Надо, надо...