LoadXML в VBA не анализирует строку в пригодном для использования DOMDocument60 - PullRequest
0 голосов
/ 22 февраля 2019

долгое время читатель, но первый пост здесь.Любая помощь очень ценится!

Я работаю над шабером данных, чтобы получить рыночные результаты наших клиентов от оператора сетки, и для этого мне нужна серия запросов xml.Я могу подключиться, аутентифицироваться и получить ответ на мой запрос, используя схему SOAP (требуется оператором сетки).Тем не менее, когда я пытаюсь загрузить XML-строку, полученную с сервера, в объект DOMDocument60 с помощью функции LoadXML, он удаляет все узлы из ответа и приводит к XML-документу только с заголовком на одном узле и объединениемвсе значения хранятся во всех узлах строки во втором узле.

Следовательно, я не могу извлечь нужные мне значения.Они имеют различную длину, и я не знаю, когда заканчивается одно значение, а начинается другое.Кроме того, поскольку имена узлов были удалены, когда я пытаюсь получить список узлов всех узлов с именем «DSRSRREGAwardHourly», я получаю пустой список.

XML, полученный от сервера после запроса (оставил только один из часовых узлов для упрощения)

<?xml version='1.0' encoding='UTF-8'?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
  <Body>
    <QueryResponse xmlns="http://emkt.pjm.com/emkt/xml">
      <DSRSRREGAwardSet>
        <DSRSRREGAward day="2018-12-01" location="1960147390">
          <DSRSRREGAwardHourly hour="1">
            <SynchOfferMW>0.5</SynchOfferMW>
            <RegOfferMW>0</RegOfferMW>
            <SelfScheduledMW>0</SelfScheduledMW>
            <SynchAwardedMW>0</SynchAwardedMW>
            <RegAwardedMW>0</RegAwardedMW>
            <RegOfferPriceUsed>0</RegOfferPriceUsed>
            <RegdOfferMW>0</RegdOfferMW>
            <RegdMW>0</RegdMW>
          </DSRSRREGAwardHourly>
        </DSRSRREGAward>
      </DSRSRREGAwardSet>
    </QueryResponse>
  </Body>
</Envelope>

Соответствующий код VBA, который я использую

'Variable definition
Dim oWinhttp As WinHttpRequest
Dim ReturnXML As MSXML2.DOMDocument60
Dim ItemList As IXMLDOMNodeList
Dim XMLItem As IXMLDOMNode

'Variable initialization
Set oWinhttp = New WinHttpRequest
Set ReturnXML = New MSXML2.DOMDocument60

'Run the query against the server
With oWinhttp
  Call .Open("POST", WebURL)
  Call .SetRequestHeader("Cookie", "pjmauth=" & tokenStr)
  Call .SetRequestHeader("Content-Type", "text/xml")
  Call .SetRequestHeader("Content-Length", Len(xmlSubmittal))
  Call .Send(xmlSubmittal)
  Call .WaitForResponse

  'Store the return XML into DOM Document
  ReturnXML.async = False
  ReturnXML.validateOnParse = False
  ReturnXML.LoadXML (.ResponseText)

  'Terminate connection
  Call oWinhttp.abort
End With

'Extract nodes we are going to need
Set ItemList = ReturnXML.SelectNodes("//DSRSRREGAwardHourly")

1 Ответ

0 голосов
/ 22 февраля 2019

Простой синтаксический анализ XML с использованием пространств имен

Попробуйте следующие строки кода

  • [1], установив определение пространства имен с помощью

    ReturnXML.setProperty "SelectionNamespaces", xmlNameSpaces

, где xmlNameSpaces - это просто строковая переменная, реплицирующая предыдущий атрибут пространства имен (xmlns) в узле <QueryResponse>.

  • [2] Выполнение базовых циклов через структуру узла.Поскольку очевидно, что в каждом узле есть только подузлы с текстовыми записями, этот пример кода не проверяет наличие пустых узлов ( Рассмотрите возможность использования более сложного синтаксического анализа XPath и / или использования специального языка запросов независимой платформы XSLT).

Соответствующий фрагмент кода

' ...
'[1] Store the return XML into DOM Document using name spaces defining a leading "d:" prefix
ReturnXML.async = False
ReturnXML.validateOnParse = False

Dim xmlNameSpaces$
xmlNameSpaces = "xmlns:d=""http://emkt.pjm.com/emkt/xml"""      ' define namespaces
ReturnXML.setProperty "SelectionNamespaces", xmlNameSpaces      ' set namespace prop

ReturnXML.LoadXML (.ResponseText)                   ' get content

'[2] Loop through node lists (attention to the chosen namespace prefix)
Dim ItemList As MSXML2.IXMLDOMNodeList, ItemList2 As MSXML2.IXMLDOMNodeList
Dim item As MSXML2.IXMLDOMNode, item2 As MSXML2.IXMLDOMNode
Set ItemList = ReturnXML.SelectNodes("//d:DSRSRREGAwardHourly") ' <~~ leading "d:" :-)

For Each item In ItemList
     Debug.Print "Day:  " & item.SelectSingleNode("../@day").Text, _
                 "Hour: " & item.SelectSingleNode("./@hour").Text
     Set ItemList2 = item.SelectNodes("d:*")
     For Each item2 In ItemList2
        Debug.Print vbTab & item2.nodeName, item2.Text
     Next item2
Next item

Ссылки по теме

Cf Получить имена атрибутов из XML, используя VBA

Приложение из-за комментария

"Мне любопытно, была ли проблема, что строка имела 2определены разные пространства имен и, следовательно, игнорирует второе? "

В основном Да ;последнее объявление в иерархии преобладает над предыдущим в вашем примере XML-данных (за исключением явно заданных имен элементов с префиксом) .

  • a) Вся структура XML в конкретном примере показывает только "normal" = имена элементов без префиксов, такие как <SynchOfferMW> (вместо возможного <extra:SynchOfferMW>, которое будетна основе дополнительного явного назначения префикса в предыдущей декларации пространства имен xmlns:extra="http://...").С нефиксированными пространствами имен вы объявляете два пространства имен по умолчанию , одно для элемента <Envelope>, второе для элемента <QueryResponse>.
  • b) Из-за w3.orgопределение пространств имен / 6.2 "область действия декларации пространства имен ► по умолчанию простирается от начала начального тега, в котором оно появляется, до конца соответствующего конечного тега, исключая область действия любого внутреннего значения по умолчаниюобъявления пространства имен. ... Объявление пространства имен по умолчанию применяется ко всем именам элементов без префикса в его области действия. " Таким образом, элемент <QueryResponse> и все его (нефиксированные) потомки этого примера принадлежат второму пространству имен по умолчанию .
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...