VBScript и loadXML: недопустимы на верхнем уровне документа. Как это исправить?

Это мой пост на stackoverflow. Я искал много похожих вопросов и ответов на этом сайте, но мои условия кажутся немного другими. вот мой код vbscript:

------------ фрагмент кода ---------------

xmlurl = "songs.xml"

set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.async = False
xmlDoc.loadXML(xmlurl)

if xmlDoc.parseError.errorcode<>0 then
  'error handling code
  msgbox("error! " & xmlDoc.parseError.reason)
end if

------------ конец кода ---------------

XML:

<?xml version="1.0" encoding="UTF-8"?>
<nowplaying-info-list>
  <nowplaying-info mountName="CKOIFMAAC" timestamp="1339771946" type="track">
    <property name="track_artist_name"><![CDATA[CKOI]]></property>
    <property name="cue_title"><![CDATA[HITMIX]]></property>
  </nowplaying-info>
  <nowplaying-info mountName="CKOIFMAAC" timestamp="1339771364" type="track">
    <property name="track_artist_name"><![CDATA[AMYLIE]]></property>
    <property name="cue_title"><![CDATA[LES FILLES]]></property>
  </nowplaying-info>
  <nowplaying-info mountName="CKOIFMAAC" timestamp="1339771149" type="track">
    <property name="track_artist_name"><![CDATA[MIA MARTINA]]></property>
    <property name="cue_title"><![CDATA[TOI ET MOI]]></property>
  </nowplaying-info>
</nowplaying-info-list>

Я также попытался удалить первую строку на случай, если UTF-8 несовместим с Windows (видел несколько сообщений об этом), но все равно получил ту же ошибку. Я также пробовал unix2dos и наоборот на случай проблем с возвратом каретки (скрытые символы, встроенные в xml). Я просто не могу понять, что не так. Это такой простой XML-файл. Я мог бы разобрать его за несколько минут, используя регулярное выражение perl, но мне нужно запустить этот скрипт в Windows, поэтому используйте vbscript. Я использую ту же технику для анализа XML из других источников без каких-либо проблем. К сожалению, я не могу изменить XML, он взят из внешнего источника. У меня точно такая же ошибка как в домашней версии Windows Vista, так и в Windows Server 2008. Пока я запускаю vbscript из командной строки для тестирования (т.е. не в ASP).

Заранее спасибо,

Сэм


person hacker101    schedule 16.06.2012    source источник


Ответы (2)


xmlDoc.loadXML() может загрузить строку XML. Он не может получить URL.

Используйте объект XMLHTTPRequest, если вам нужно сделать HTTP-запрос.

Function LoadXml(xmlurl)
  Dim xmlhttp

  Set xmlhttp = CreateObject("MSXML2.XMLHTTP")
  xmlhttp.Open "GET", xmlurl, false

  ' switch to manual error handling
  On Error Resume Next

  xmlhttp.Send
  If err.number <> 0 Then 
    WScript.Echo xmlhttp.parseError.Reason
    Err.Clear
  End If 

  ' switch back to automatic error handling 
  On Error Goto 0

  Set LoadXml = xmlhttp.ResponseXml
End Function

Используйте как

Set doc = LoadXml("http://your.url/here")
person Tomalak    schedule 16.06.2012
comment
Ваше решение сработало, но с небольшой модификацией. Вместо: Set xmldoc = xmlhttp.ResponseXml Я изменил свою функцию загрузки (после HTTP GET): xmlDoc.loadXML(xmlhttp.responseText) Большое спасибо, теперь у меня больше нет ошибок! Теперь мне просто нужно выяснить, как анализировать атрибуты узлов и эти забавные вещи !CDATA[] LOL. - person hacker101; 16.06.2012
comment
@hacker101 Но почему? responseXML уже является вполне допустимым объектом XML-документа. Нет никакой необходимости разбирать responsText снова. Все, что вы делаете, это создаете второй объект документа, отбрасывая первый. - person Tomalak; 16.06.2012
comment
Раньше почему-то выдавал ошибку. Ты прав! Это намного лучше, меньше кода и меньше накладных расходов во время выполнения. классно. Спасибо еще раз! - person hacker101; 16.06.2012
comment
@Hacker101 Не забудьте принять ответ. :) Кстати, хороший первый вопрос. Код, пояснения, все есть. Вот как это должно быть. - person Tomalak; 16.06.2012

Три дополнительных замечания:

(1) Поскольку .parseError.reason имеет тенденцию быть загадочным, стоит включить его свойство .srcTxt (и параметр для .loadXml):

  Dim xmlurl : xmlurl = "song.xml"
  Dim xmlDoc : Set xmlDoc = CreateObject("Microsoft.XMLDOM")
  xmlDoc.async = False
  xmlDoc.loadXML xmlurl
  If 0 <> xmlDoc.parseError.errorcode Then
     WScript.Echo xmlDoc.parseError.reason, "Src:", xmlDoc.parseError.srcText
  Else
     WScript.Echo "surprise, surprise"
  End if

выход:

Invalid at the top level of the document.
 Src:  song.xml

Конечно, написать функцию/подпрограмму, которая учитывает все свойства .parseError и использовать ее всегда, было бы еще лучше.

(2) Чтобы загрузить файл или URL-адрес, используйте .load:

  Dim xmlDoc : Set xmlDoc = CreateObject("Microsoft.XMLDOM")
  Dim xmlurl
  For Each xmlurl In Array("song.xml", "http://gent/~eh/song.xml", "zilch")
    xmlDoc.async = False
    if xmlDoc.load(xmlurl) Then
       With xmlDoc.documentElement.firstChild
          WScript.Echo    xmlurl _
                       , .tagName _
                       , .firstChild.tagName _
                       , .firstChild.text
       End With
    Else
       WScript.Echo xmlurl, xmlDoc.parseError.reason, "Src:", xmlDoc.parseError.srcText
    End if
  Next

выход:

song.xml nowplaying-info property CKOI-ÄÖÜ
http://gent/~eh/song.xml nowplaying-info property CKOI-ÄÖÜ
zilch The system cannot locate the object specified.
 Src:

(3) Использование DOM позволяет избежать всех проблем с кодировкой (поэтому я поместил несколько умлаутов на немецком языке в «ваш» файл, который даже попал в вывод DOS-Box) и делает RegExps (даже Perl) вторым лучшим выбором.

person Ekkehard.Horner    schedule 16.06.2012
comment
Очень хороший ответ. Также спасибо за подсказки (т.е. текст ошибки синтаксического анализа). - person hacker101; 27.06.2012
comment
+1. Полезные дополнения. Я не знал, что XMLDOM может загружаться с URL-адресов. - person Tomalak; 27.06.2012