Xpoint
   [напомнить пароль]

msxml и проблема с namespace

Метки: [без меток]
2007-06-07 10:50:51 [обр] Evgenia[досье]
сообщение промодерировано

Добрый день.

Есть примерно такой файл:

<?xml version="1.0" encoding="windows-1251"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="http://..." extension-element-prefixes="my"> 
<my:element> 
<name>название</name> 
</my:element> 
</xsl:stylesheet>

Мне нужно в vbs-скрипте открыть этот файл, найти все элементы my:element и для каждого вывести тег name.

Пишу так:

dim xmlfile 
set xmlfile = LoadDocument (filename) 
xmlfile.setProperty "SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:my='http://...'" 
set elems = xmlfile.selectNodes("//my:element") 
for each elem in elems 
if elem.selectNodes("name").length=1 then 
WScript.Echo elem.selectSingleNode("name") 
end if 
next

В функции LoadDocument используется объект Msxml2.DOMDocument.4.0

В результате вижу, что узлы name не находятся, хотя они точно есть в исходном файле.

Что я делаю не так? Подскажите, пожалуйста.

спустя 23 минуты [обр] GRAy(64/259)[досье]
НМВЗ, из-за того что в инструкции xmlfile.setProperty "SelectionNamespaces"... вы явно указали узлы из каких namespac`ов хотите выбирать дальнейшее использование elem.selectNodes("name") и д.р. подпадает под это ограничение, и, т.к. узел name находится в дефолтном namespac`е - вы ничего не получаете. Возможно это из той же степи что и вот это.
спустя 36 минут [обр] Evgenia[досье]
К сожалению, я не могу менять исходный документ, так что задачу надо решить на стороне скрипта. Есть ли такая возможность?
спустя 27 минут [обр] GRAy(64/259)[досье]

Может быть так (проверить не могу к сожалению):

dim xmlfile 
set xmlfile = LoadDocument (filename) 
xmlfile.setProperty "SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform' xmlns:my='http://...' xmlns:default="http://www.w3.org/2001/XMLSchema"
set elems = xmlfile.selectNodes("//my:element") 
for each elem in elems 
if elem.selectNodes("default:name").length=1 then 
WScript.Echo elem.selectSingleNode("default:name") 
end if 
next

Я просто определил для умолчательного namespac`а явный префикс и далее использовал его в selectNodes соответственно.

спустя 21 минуту [обр] Evgenia[досье]

Да, да, да! Заработало. Спасибо огромное!

И сразу второй вопрос, в развитие этой же задачи:

В исходный документ добавляю:
<!DOCTYPE xsl:stylesheet SYSTEM "symbols.ent">

И при обращении к нему получаю ошибку:
You have error The element 'xsl:stylesheet' is used but not declared in the DTD/
Schema.

Что тут не так?

спустя 14 минут [обр] GRAy(64/259)[досье]
Evgenia[досье] А что это вообще должно означать?
спустя 2 минуты [обр] Evgenia[досье]
Это подключение внешнего файла с описанием сущностей.
спустя 3 часа 24 минуты [обр] GRAy(64/259)[досье]
Дык, с помощью такого объявления вы говорите, что некий внешний dtd должен описывать структуру вашего документа начиная с корневого элемента xls:stylesheet. Определения этого элемента, я подозреваю, в dtd нет - собственно на это он и ругается, т.к. не может отвалидировать документ согласно указаному DTD. Нельзя указать DTD в котором есть только определения ENTITY, и более того - DOCTYP`а для xsl, насколько мне известно, не существует, есть только схема (XSD). Единственный способ включить дополнительные сущности в документ c неподкотрольной вам структуре это inline DOCTYPE - т.е.
<?xml version="1.0" ?>
<!DOCTYPE stylesheet [
  <!ENTITY ntilde  "&#241;" >
  ...
]>
<xsl:stylesheet>
...
спустя 23 минуты [обр] Evgenia[досье]
Странно то, что описанный мной вариант подключения списка сущностей работает. Проверено.
Да и вот, например, прямое указание делать именно так:
http://www.artlebedev.ru/tools/technogrette/xslt/namespace_definition/
И только при чтении файла с помощью msxml это не проходит. Предложенный вами вариант (даже если бы я могла изменить исходный текст документа), к сожалению, не избавляет от ошибки - она по прежнему появляется.
спустя 1 час 52 минуты [обр] GRAy(64/259)[досье]
Evgenia[досье] Указание немного о другом. Ко всему прочему в элементарном тесте оно у меня не работает, правда и ошибка другого толка (stylesheet does not contain a document element). Видимо тут уже начинает играть роль версия xml-процессора. Приведите работающий пример исходного xsl`я (с использованием doctype), вашего dtd (можно не полностью) и кода которым вы что-то с ним делаете.
спустя 16 часов [обр] Evgenia[досье]
сообщение промодерировано

xsl:

<?xml version="1.0" encoding="windows-1251"?>
<!DOCTYPE xsl:stylesheet SYSTEM "symbols.ent">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" encoding="windows-1251" indent="yes"/>
  <xsl:template match="/">
    word&nbsp;word
  </xsl:template>
</xsl:stylesheet>

symbols.ent:

<?xml version="1.0" encoding="windows-1251" ?>
<!ENTITY   nbsp   "&#160;">

код:

dim xmlfile
set xmlfile = LoadDocument (filename)

function NewDocument()
   dim doc
   set doc = CreateObject("Msxml2.DOMDocument.4.0")
   doc.loadXML "<?xml version='1.0' encoding='windows-1251' ?><root/>"
   set NewDocument = doc
end function

function LoadDocument(name)
   dim err
   dim xml
   set xml = NewDocument()
   xml.async = False
   if fso.FileExists(name) then 
      xml.Load (name)
      set err = xml.parseError
      if (err.errorCode <> 0) then
         WScript.Echo "You have error " & err.reason & " for " & name
      end if
   end if
   set LoadDocument = xml
end function
спустя 5 часов [обр] Evgenia[досье]
Я нашла решение этой проблемы. При создании DOM-документа надо указывать doc.validateOnParse = false и тогда мой способ объявления сущностей вызывать ошибку не будет. Не самый красивый способ, полагаю, но работающий.
спустя 8 часов [обр] GRAy(64/259)[досье]
А я так и не смог проверить толком ;)
У меня старая версия MSXML, а на рабочем компе нет админских прав, чтобы установить версию поновее.
Powered by POEM™ Engine Copyright © 2002-2005