Ссылка на необъявленный префикс пространства имен при разборе MSXML
Как мне решить
Reference to undeclared namespace prefix: '%s'
проблема с реализацией Microsoft msxml?
Я использую XML-фид с правительственного веб-сайта, который содержит значения, которые мне нужно проанализировать. Xml содержит пространства имен:
<?xml version="1.0" encoding="ISO-8859-1"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://purl.org/rss/1.0/"
xmlns:cb="http://www.cbwiki.net/wiki/index.php/Specification_1.1"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3c.org/1999/02/22-rdf-syntax-ns#rdf.xsd">
<item rdf:about="http://www.bankofcanada.ca/stats/rates_rss/STATIC_IEXE0101.xml">
<cb:statistics>
<cb:exchangeRate>
<cb:value decimals="4">1.0351</cb:value>
<cb:baseCurrency>CAD</cb:baseCurrency>
<cb:targetCurrency>USD</cb:targetCurrency>
<cb:rateType>Bank of Canada noon rate</cb:rateType>
<cb:observationPeriod frequency="daily">2011-05-09T12:15:00-04:00</cb:observationPeriod>
</cb:exchangeRate>
</cb:statistics>
</item>
</rdf:RDF>
Запуск запроса XPath:
/rdf:RDF/item/cb:statistics/cb:exchangeRate/cb:targetCurrency
не удается выполнить ошибку:
Reference to undeclared namespace prefix: 'rdf'
Edit
Если я отредактирую исходный XML, чтобы удалить все использование пространств имен:
<?xml version="1.0" encoding="ISO-8859-1"?>
<rdf>
<item>
<statistics>
<exchangeRate>
<value decimals="4">1.0351</value>
<baseCurrency>CAD</baseCurrency>
<targetCurrency>USD</targetCurrency>
<rateType>Bank of Canada noon rate</rateType>
<observationPeriod frequency="daily">2011-05-09T12:15:00-04:00</observationPeriod>
</exchangeRate>
</statistics>
</item>
</rdf>
Запрос /rdf/item/statistics/exchangeRate/baseCurrency
не прерывается и возвращает узлы:
<baseCurrency>CAD</baseCurrency>
Как заставить Microsoft XML работать с пространствами имен?
Изменить 2
Я попытался добавить SelectionNamespaces к объекту DOMDocument:
doc.setProperty('SelectionNamespaces', 'xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cb="http://www.cbwiki.net/wiki/index.php/Specification_1.1"');
Теперь запрос xpath не прерывается, но он также не возвращает узлов:
nodes = doc.selectNodes('/rdf:RDF/item/cb:statistics/cb:exchangeRate/cb:targetCurrency');
См. также
Ответы
Ответ 1
Использование SelectionNamespaces
- правильный подход, вам просто не хватает пространства имен.
Обратите внимание, что ваш XML-документ явно задает пространство имен по умолчанию следующим образом:
xmlns="http://purl.org/rss/1.0/"
Это означает, что любой элемент без префикса, такой как элемент item
, фактически находится в пространстве имен по умолчанию. Поэтому, если вы хотите выбрать этот элемент с выражением XPath, вы должны сначала установить подходящее пространство имен.
Чтобы сделать это, вы можете изменить свой вызов на setProperty
следующим образом:
doc.setProperty('SelectionNamespaces', 'xmlns:rss="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cb="http://www.cbwiki.net/wiki/index.php/Specification_1.1"');
Здесь вы назначили пространство имен по умолчанию из документа в префикс rss:
в выражении XPath. С учетом этого изменения следующее выражение XPath должно работать правильно:
nodes = doc.selectNodes('/rdf:RDF/rss:item/cb:statistics/cb:exchangeRate/cb:targetCurrency');
Он работает, потому что он ссылается на элемент item
, используя правильное пространство имен. Тот факт, что префикс отличается между выражением XPath и исходным документом, не имеет значения. Это пространство имен, к которому привязан префикс.
Ответ 2
doc.setProperty('SelectionNamespaces', 'xmlns:rss="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cb="http://www.cbwiki.net/wiki/index.php/Specification_1.1"');
Не забывайте загружать xsd файл или схему в объект xmldoc
- это путь
У меня нет достаточной репутации для комментариев. Но этот бит спас меня много времени.
Большое вам спасибо
Ответ 3
Если вы используете XMLSerializer
и видите эту ошибку, вполне вероятно, что вы столкнулись с ошибкой IE, описанной здесь:
fooobar.com/info/368164/...
Мне потребовалось много времени, чтобы понять, что это происходит, поэтому я подумал, что лучше всего связать эти два вопроса.