Ссылка на необъявленный префикс пространства имен

У меня есть файл XML, который выглядит так:

<xc:XmlCache xmlns:xc="XmlCache" xmlns:mp="mx.MarketParameters" xmlns:rt="mx.MarketParameters.Rates" xmlns:rtcu="mx.MarketParameters.Rates.Curve">
    <xc:XmlCacheArea xc:value="MarketParameters">
        <mp:nickName xc:value="MDS" xmlns:mp="mx.MarketParameters">
            <mp:date xc:value="20160518">
                <rt:rate xmlns:rt="mx.MarketParameters.Rates">
                    <rtcu:curve xmlns:rtcu="mx.MarketParameters.Rates.Curve">
                        <rtcu:currency xc:value="AED">
                            <rtcu:label xc:value="AED FX">
                                <rtcu:type xc:value="Swap point">
                                    <rtcu:generator xc:value="USD/AED">
                                        <rtcu:market xc:value="">
                                            <rtcu:maturity xc:value="10M" xc:dates="20160523-20170323" xc:type="Fields">

Я хотел бы получить список узлов типа rtcu:maturity в VBA для выполнения некоторых операций:

Dim xmlCurvesFileDOMDocument As New DOMDocument60
Dim listOfMaturities As IXMLDOMNodeList

xmlCurvesFileDOMDocument.Load (xmlCurvesFilePath)
Set listOfMaturities = xmlCurvesFileDOMDocument.SelectNodes("//xc:XmlCache/xc:XmlCacheArea/mp:nickName/mp:date/rt:rate/rtcu:curve/rtcu:currency/rtcu:label/rtcu:type/rtcu:generator/rtcu:market/rtcu:maturity")

(примечание: я опускаю xmlCurvesFilePath, но это правильно, файл загружается).

Когда я запускаю это, на наборе listOfMaturities я получаю ошибку типа Reference to undeclared namespace prefix: 'xc'. Если я уберу xc из пути, он скажет мне, что проблема в другом (mp). Если я удалю все пространства имен из XPath, это сработает, но ничего не загрузит.

Я пытался найти переполнение стека, и кажется, что решением будет установка пространств имени выбора (например, здесь и здесь).

Однако, когда я пытаюсь это сделать:

xmlCurvesFileDOMDocument.setProperty("SelectionNamespaces", "xmlns:xc='XmlCache'")

... Я получаю сообщение об ошибке компиляции "Expected : =".

Кто-нибудь знает, как я могу объявить свои пространства имен и проанализировать этот файл XML?


person Matteo NNZ    schedule 23.02.2018    source источник
comment
Не используйте скобки при вызове методов в VBA: xmlCurvesFileDOMDocument.setProperty "SelectionNamespaces", "xmlns:xc='XmlCache'"   -  person Fratyx    schedule 23.02.2018
comment
@Fratyx Я понял, что пока StackOverflow некоторое время не работал. Я думаю, вы должны написать это как ответ, так как это было реальным решением!   -  person Matteo NNZ    schedule 23.02.2018
comment
Проблема была не только в типографике, но и в том, что пользователь не назначил весь набор пространств имен для получения нодлиста XML :-)   -  person T.M.    schedule 23.02.2018


Ответы (3)


Загрузить файл XML, включая пространства имен

Вы не установили пространства имен перед загрузкой, попробуйте этот код, включая процедуру загрузки ошибок:

Option explicit             ' declaration head of code module

Sub LoadIt()
Dim xmlCurvesFilePath        As String
    xmlCurvesFilePath = ThisWorkbook.Path & "\xml\testxc.xml"  ' << change to your xml file

Dim xmlCurvesFileDOMDocument As New DOMDocument60
Dim listOfMaturities         As IXMLDOMNodeList
Dim XmlNamespaces            As String
   ' [*** define Namespaces ***] ' <<< NAMESPACE DEFINITION NEEDED :-)
    XmlNamespaces = "xmlns:xc='XmlCache' xmlns:mp='mx.MarketParameters' xmlns:rt='mx.MarketParameters.Rates' xmlns:rtcu='mx.MarketParameters.Rates.Curve'"

With xmlCurvesFileDOMDocument
    .setProperty "SelectionNamespaces", XmlNamespaces
    .setProperty "SelectionLanguage", "XPath"
    .resolveExternals = True
    .validateOnParse = True
    .async = False
    If .Load(xmlCurvesFilePath) Then   ' check correct loading
       Set listOfMaturities = .SelectNodes("//xc:XmlCache/xc:XmlCacheArea/mp:nickName/mp:date/rt:rate/rtcu:curve/rtcu:currency/rtcu:label/rtcu:type/rtcu:generator/rtcu:market/rtcu:maturity")
       Debug.Print listOfMaturities.Length
    Else
       Dim xPE        As Object    ' Set xPE = CreateObject("MSXML2.IXMLDOMParseError")
       Dim strErrText As String
       Set xPE = xmlCurvesFileDOMDocument.parseError
       With xPE
           strErrText = "Load error " & .ErrorCode & " xml file " & vbCrLf & _
          Replace(.URL, "file:///", "") & vbCrLf & vbCrLf & _
           xPE.reason & _
          "Source Text: " & .srcText & vbCrLf & vbCrLf & _
          "Line No.:    " & .Line & vbCrLf & _
          "Line Pos.: " & .linepos & vbCrLf & _
          "File Pos.:  " & .filepos & vbCrLf & vbCrLf
      End With
      MsgBox strErrText, vbExclamation
      Set xPE = Nothing
      Exit Sub
    End If
End With

' further code
' ...
' clear memory
Set xmlCurvesFileDOMDocument = Nothing
End Sub
person T.M.    schedule 23.02.2018
comment
Наконец, речь шла только об удалении скобок из команды setProperty. В любом случае спасибо за ответ, +1! - person Matteo NNZ; 23.02.2018
comment
Рад, что это сработало с правильным синтаксисом и объявлением полного набора пространств имен. Кстати, избегайте установки скобок в утверждениях, вы можете столкнуться с проблемами; например ваша загрузка XML в OP через xmlCurvesFileDOMDocument.Load (xmlCurvesFilePath) не нуждается в скобках, тогда как вариант функции, показанный в моем ответе If xmlCurvesFileDOMDocument.Load(xmlCurvesFilePath) Then, должен иметь их в любом случае. - person T.M.; 23.02.2018

Использование Xml Linq

Imports System.Xml
Imports System.Xml.Linq
Module Module1
    Const FILENAME As String = "c:\temp\test.xml"
    Sub Main()
        Dim doc As XDocument = XDocument.Load(FILENAME)
        Dim namespaces = doc.Descendants().Select(Function(x) New With {.ns = IIf(x.ToString().Contains(":"), x.ToString().Substring(1, x.ToString().IndexOf(":")), String.Empty), .name = x.Name.LocalName}).ToArray()
    End Sub

End Module
person jdweng    schedule 23.02.2018
comment
К сожалению, я использую VBA, а не VB.NET :( - person Matteo NNZ; 23.02.2018

Наконец, ошибка была просто синтаксической. Вместо этого:

xmlCurvesFileDOMDocument.setProperty("SelectionNamespaces", "xmlns:xc='XmlCache'")

... Пришлось писать без скобок, объявляя все пространства имён:

xmlCurvesFileDOMDocument.setProperty "SelectionNamespaces", "xmlns:xc='XmlCache' xmlns:mp='mx.MarketParameters'" etc.
person Matteo NNZ    schedule 23.02.2018