Загрузка HTML-документа в синтаксическом анализаторе DOM XML в VBScript завершается ошибкой, если присутствует тег ‹!DOCTYPE html›

В настоящее время я пытаюсь использовать VBScript для выполнения пакетных изменений файлов HTML. Для этого я использую объект Microsoft.XMLDOM. Не удается загрузить мой HTML-файл в виде XML-документа. После некоторых экспериментов выяснилось, что виновником является следующий тег, находящийся в первой строке:

<!DOCTYPE html>

Если эту строку убрать, мой скрипт будет работать как положено. Если эта строка включена, она не будет загружаться. Никакого конкретного сообщения об ошибке не появляется, но попытка получить что-либо из объекта XMLDOM ничего не вернет, что является тем же самым поведением, когда файл, который объект пытается загрузить, не существует.

Кто-нибудь знает, почему это происходит и как это обойти? Я не могу удалить этот тег из своих файлов, поскольку они представляют собой HTML-документы и регулярно регенерируются другим приложением.

Вот пример моего кода:

strFilePath = WScript.Arguments(0)
strTitlePrefix = WScript.Argument(1)

Set objXMLDoc = CreateObject("Microsoft.XMLDOM")
objXMLDoc.Async = False

objXMLDoc.load(strFilePath)

Set objDoc = objXMLDoc.documentElement
Set objNodes = objDoc.selectNodes("//title")
For Each thisNode in objNodes
  OriginalTitle = thisNode.text
  NewTitle = TitlePrefix & OriginalTitle
  thisNode.text = NewTitle     
Next

Это терпит неудачу в этой строке:

Set objNodes = objDoc.selectNodes("//title")

Это сообщение об ошибке:

Microsoft VBScript runtime error: Object required: 'objDoc'

Код делает то, что я ожидаю, если я удалю тег в верхней части документа, который он пытается прочитать, поэтому я знаю, что проблема в том, что этот тег заставляет его думать, что файл не является XML-документом.


person Quote    schedule 05.07.2018    source источник
comment
Microsoft.XMLDOM устарел, используйте вместо него Msxml2.DOMDocument.6.0. Для получения дополнительной помощи с вашим кодом: пожалуйста, покажите свой код.   -  person Ansgar Wiechers    schedule 05.07.2018
comment
Пожалуйста, отредактируйте свой вопрос и добавьте свой код!   -  person Hackoo    schedule 06.07.2018
comment
Я добавил свой код.   -  person Quote    schedule 06.07.2018
comment
@AnsgarWiechers Я только что попробовал, чтобы мой код загружал объект Msxml2.DOMDocument.6.0, и, к сожалению, это не имело значения. Спасибо.   -  person Quote    schedule 06.07.2018


Ответы (1)


Во-первых, вы можете сузить круг причин проблемы, добавив проверку ошибок после load:

objXMLDoc.load(strFilePath)
If objXMLDoc.parseError.errorCode <> 0 Then
   MsgBox "ERROR when loading " + strFileName + ": " + objXMLDoc.parseError.reason
End If

(В зависимости от вашей среды VBScript вам, возможно, придется использовать что-то еще, кроме MsgBox.)

Вы, вероятно, получите сообщение об ошибке

ошибка: DTD запрещен.

Причина в том, что загрузка синтаксиса DTD (например, !DOCTYPE) по умолчанию запрещена в MSXML 6.0. См. Обзор безопасности MSXML для подробностей. Вот соответствующая часть

Некоторые части XML (такие как DTD и встроенные схемы) по своей природе рискованны. В стандартной конфигурации установки MSXML 6.0 эти функции отключены. Вы можете включить эти функции, но сначала вы должны убедиться, что риски безопасности, связанные с ними, не относятся к вам.

Если вы попытаетесь загрузить DTD без явного включения свойства ProhibitDTD, вы получите следующую ошибку:

ошибка: DTD запрещен.

Если добавить строку

objXMLDoc.setProperty "ProhibitDTD", False

перед загрузкой ошибка DTD is probited больше не возникнет.

Вам, скорее всего, также придется добавить строку

objXMLDoc.validateOnParse = False

перед загрузкой, если ваш HTML-файл не содержит полного HTML DTD (при этом его обычно нет).

Подводя итог, вот полный код:

strFilePath = "C:\Temp\test.html"

Set objXMLDoc = CreateObject("Msxml2.DOMDocument.6.0")
objXMLDoc.Async = False
objXMLDoc.setProperty "ProhibitDTD", False
objXMLDoc.validateOnParse = False
objXMLDoc.load(strFilePath)
If objXMLDoc.parseError.errorCode <> 0 Then
   MsgBox "ERROR when loading " + strFileName + ": " + objXMLDoc.parseError.reason
End If

Set objDoc = objXMLDoc.documentElement

MsgBox TypeName(objDoc)
Set objNodes = objDoc.selectNodes("//title")
MsgBox objNodes.Length

Он может успешно загрузить и проанализировать этот файл:

<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>

<body>
The content of the document......
</body>

</html> 

В последней строке будет выведено «1», так как тег только один.

Однако обратите внимание, что есть один недостаток: HTML — это не XML! Т.е. не каждый HTML-файл является правильно сформированным XML-файлом. Например. если в приведенном выше образце HTML-файла будет тег <br> (без соответствия </br>), загрузка завершится ошибкой. Вышеупомянутым методом можно открыть только HTML-файлы, совместимые с XML.

person FrankM    schedule 06.07.2018
comment
Спасибо. Это именно то, что мне было нужно. Вы знаете, где я могу найти ссылку на метод setProperty и его доступные свойства? Я использую следующий веб-сайт, и, похоже, на нем нет этой информации: devguru .com/content/technologies/xml_dom/home.html - person Quote; 06.07.2018
comment
Кроме того, это правда, что я беру на себя риск, обрабатывая файлы HTML с помощью синтаксического анализатора XML. Я постараюсь создать собственную логику синтаксического анализа, поскольку изменения, которые я хочу внести в сценарий, очень просты. Спасибо за совет. - person Quote; 06.07.2018
comment
@Bluewoods Свойства описаны в Свойства DOM второго уровня. - person FrankM; 07.07.2018