Измельчение XML в VB6 / найти максимальное значение атрибута

Я новичок в SO- я надеюсь, что отправлю это в нужном месте.

Как обновление моего поста ниже, я нашел один способ получить часть адреса в City. Мне действительно не нужно максимальное значение, как предложено в моем первоначальном посте; Мне просто нужно последнее значение, потому что значения "xyz:sequenceNumber" всегда, ну, в последовательности. Итак, я попробовал это:

tmpCity = xNode.selectSingleNode("//abc:Person//xyz:Region").previousSibling.Text

и это похоже на работу, так как я имею дело с хорошо отформатированными файлами.xml, в которых предыдущий параметр xyz:Region всегда является последней строкой xyz:AddressText, содержащей искомое значение City. Я все еще буду благодарен за любые комментарии, потому что я остаюсь в неведении относительно того, является ли это (и код ниже) даже отдаленно эффективным. У меня есть много больших XML-файлов, поэтому эффективность имеет значение.

Мне нужно работать с некоторым устаревшим кодом VB6, который включает в себя рекурсивную подпрограмму уничтожения XML. Я знаком с VB6, но я не понимаю эту подпрограмму. Я вставил часть кода ниже. Я надеюсь, что кто-то может подсказать мне некоторые подробные справочные материалы для чтения, которые помогут мне понять, как работают аспекты обработки XML в этой подпрограмме, чтобы я мог поддерживать и изменять его. Я также вставил ниже [санированный] пример выдержки из двух файлов XML, с которыми мне нужно работать. Одна из проблем заключается в том, что часть адреса City хранится в последнем из перечисленных атрибутов. Чтобы получить Город, мне нужно извлечь текст из атрибута с максимальным значением xyz: sequenceNumber. У SO много постов с примерами того, как получить атрибут наибольшего значения, но я не могу заставить их работать в этой подпрограмме. Как правило, они, кажется, используют либо функцию max () - на что VB6 жалуется, когда я пытаюсь использовать ее в этой подпрограмме; или они используют что-то вроде того, что вы видите в фрагменте ниже, но когда я пытаюсь приспособиться, VB6 жалуется на двойное двоеточие ("::").

doc.SelectSingleNode("//Employees/Employee/@Id[not(. <=../preceding-sibling::Employee/@id) and not(. <=../following-sibling::Employee/@Id)]");

Я предполагаю, что примеры, которые я видел, относятся к библиотекам, отличным от того, что доступно в VB6.

Вот пример XML:

<abc:Person>
  <xyz:LicenseNo>1234</xyz:LicenseNo>
  <xyz:Language xyz:languageCode="en">
    <xyz:Name>
      <xyz:Company xyz:languageCode="en">ABC Company Ltd.</xyz:Company>
    </xyz:Name>
    <xyz:AddressCollection>
      <xyz:Address>
        <xyz:SequencedAddress xyz:languageCode="en">
          <xyz:AddressText xyz:sequenceNumber="1">The ABC Building</xyz:AddressText>
          <xyz:AddressText xyz:sequenceNumber="2">123 Main Street</xyz:AddressText>
          <xyz:AddressText xyz:sequenceNumber="3">3rd Floor</xyz:AddressText>
          <xyz:AddressText xyz:sequenceNumber="4">Tampa</xyz:AddressText>
          <xyz:Region xyz:RegionCategory=“State”>FL</xyz:Region>
          <xyz:CountryCode>US</xyz:CountryCode>
          <xyz:ZipCode>33607</xyz:ZipCode>
        </xyz:SequencedAddress>
      </xyz:Address>
    </xyz:AddressCollection>
  </xyz:Language>
</abc:Person>
<abc:Person>
  <xyz:LicenseNo>567</xyz:LicenseNo>
  <xyz:Language xyz:languageCode="en">
    <xyz:Name>
      <xyz:Company xyz:languageCode="en">XYZ Industries Ltd.</xyz:Company>
    </xyz:Name>
    <xyz:AddressCollection>
      <xyz:Address>
        <xyz:SequencedAddress xyz:languageCode="en">
          <xyz:AddressText xyz:sequenceNumber="1">XYZ Factory Plaza</xyz:AddressText>
          <xyz:AddressText xyz:sequenceNumber="2">678 Elm Street</xyz:AddressText>
          <xyz:AddressText xyz:sequenceNumber="3">Orlando</xyz:AddressText>
          <xyz:Region xyz:RegionCategory=“State”>FL</xyz:Region>
          <xyz:CountryCode>US</xyz:CountryCode>
          <xyz:ZipCode>32814</xyz:ZipCode>
        </xyz:SequencedAddress>
      </xyz:Address>
    </xyz:AddressCollection>
  </xyz:Language>
</abc:Person>

Вот часть кода:

Public Sub ShredXML(ByRef Nodes As MSXML2.IXMLDOMNodeList)
Dim xNode As MSXML2.IXMLDOMNode

    For Each xNode In Nodes
            If xNode.nodeType = NODE_ELEMENT Then
                If xNode.nodeName = "abc:Person" Then
                tmpCompany = xNode.selectSingleNode("//abc:Person//xyz:Company").Text
                tmpLicenseNo = xNode.selectSingleNode("//abc:Person//xyz:LicenseNo").Text
                tmpLanguage = xNode.selectSingleNode("//abc:Person//xyz:Language").Attributes.getNamedItem("xyz:languageCode").Text
                tmpRegion = xNode.selectSingleNode("//abc:Person//xyz:Region").Text
                tmpCountryCode = xNode.selectSingleNode("//abc:Person//xyz:CountryCode").Text
                tmpZipCode = xNode.selectSingleNode("//abc:Person//xyz:ZipCode").Text

‘ database insert code omitted

                End If
            End If

        If xNode.hasChildNodes Then
            ShredXML xNode.childNodes
        End If

   Next xNode

1 ответ

Я взял ваш образец XML-фрагмента, исправил ошибки (использовались неверные кавычки, “State” вместо "State"), затем оберните его внутри узла документа:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<doc xmlns:abc="urn:abc" xmlns:xyz="urn:xyz">
:
</doc>

Сохранено как sample.xml и запустил этот код:

Option Explicit

Private Sub WriteLine(Optional ByVal Text As String)
    With Text1
        .SelStart = &H7FFF 'End.
        If Len(Text) > 0 Then .SelText = Text
        .SelText = vbNewLine
    End With
End Sub

Private Sub Form_Load()
    Dim ParseSuccess As Boolean
    Dim Element1 As MSXML2.IXMLDOMElement
    Dim Element2 As MSXML2.IXMLDOMElement
    Dim LicenseNo As String
    Dim Company As String
    Dim Language As String
    Dim Region As String
    Dim CountryCode As String
    Dim ZipCode As String
    Dim MaxSeqVal As Long
    Dim MaxSeqElement As MSXML2.IXMLDOMElement
    Dim SeqVal As Long
    Dim City As String

    With New MSXML2.DOMDocument60
        ParseSuccess = .Load(App.Path & "\sample.xml")
        WriteLine "Parse success = " & CStr(ParseSuccess)
        If ParseSuccess Then
            WriteLine
            For Each Element1 In .getElementsByTagName("abc:Person")
                With Element1
                    LicenseNo = .getElementsByTagName("xyz:LicenseNo")(0).Text
                    Company = .getElementsByTagName("xyz:Company")(0).Text
                    Set Element2 = .getElementsByTagName("xyz:Language")(0)
                    Language = Element2.getAttribute("xyz:languageCode")
                    Region = .getElementsByTagName("xyz:Region")(0).Text
                    CountryCode = .getElementsByTagName("xyz:CountryCode")(0).Text
                    ZipCode = .getElementsByTagName("xyz:ZipCode")(0).Text
                    MaxSeqVal = -1
                    For Each Element2 In .getElementsByTagName("xyz:AddressText")
                        SeqVal = CLng(Element2.getAttribute("xyz:sequenceNumber"))
                        If SeqVal > MaxSeqVal Then
                            MaxSeqVal = SeqVal
                            Set MaxSeqElement = Element2
                        End If
                    Next
                    City = MaxSeqElement.Text
                End With
                WriteLine LicenseNo
                WriteLine Company
                WriteLine Language
                WriteLine Region
                WriteLine CountryCode
                WriteLine ZipCode
                WriteLine City
                WriteLine
            Next
        End If
    End With
End Sub

Обратите внимание, что интерфейсы Node и Element имеют разные члены (свойства и методы), поэтому Element1 а также Element2 используются здесь. Это позволяет нам взять Node и запросить его более полезный интерфейс Element.

Казалось, работает нормально:

Parse success = True

1234
ABC Company Ltd.
en
FL
US
33607
Tampa

567
XYZ Industries Ltd.
en
FL
US
32814
Orlando

Насколько мне известно, MSXML не поддерживает XPath 2, поэтому операция "max" не поддерживается.

Другие вопросы по тегам