Измельчение 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" не поддерживается.