Как создать цикл для узла, который не всегда может быть частью его родителя - при анализе данных для других узлов?VBA XML DOM Поиск элемента, который может не всегда существовать
Предположим, у вас есть очень большой файл с несколькими из этих элементов, но для простоты мы будем использовать этот XML (обратите внимание на первую «книгу идентификатор» не имеет узел, мы хотим, поэтому наш цикл уже не удается):
<?xml version="1.0"?>
<catalog>
<book id="Adventure" ISBN="00113" version="13">
<author>Ralls, Kim</author>
<title>XML Developer's Guide</title>
<price>44.95</price>
<misc>
<editor id="9B">
<editorBrand>Partial Edit</editorBrand>
<editorEmphasis>Minimal</editorEmphasis>
</editor>
</misc>
</book>
<book id="Adventure" ISBN="00114" version="14">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<price>5.95</price>
<misc>
<Publisher id="5691">
<PublisherLocation>Los Angeles</PublisherLocation>
</Publisher>
<PublishedAuthor id="Ralls">
<StoreLocation>Store A/8</StoreLocation>
<seriesTitle>AAA</seriesTitle>
<store id="8">
<copies>26</copies>
</store>
</misc>
</book>
<book id="Adventure" ISBN="00115" version="14">
<author>Ralls, Kim</author>
<title>Mist</title>
<price>15.95</price>
<misc>
<Publisher id="8101">
<PublisherLocation>New Mexico</PublisherLocation>
</Publisher>
<PublishedAuthor id="Ralls">
<StoreLocation>Market C/13</StoreLocation>
<seriesTitle>BBB</seriesTitle>
<store id="9">
<copies>150</copies>
</store>
<store id="13">
<copies>60</copies>
</store>
</PublishedAuthor>
</misc>
</book>
<book id="Mystery" ISBN="00116" version="13">
<author>Bill, Simmons</author>
<title>NBA Insider</title>
<price>16.99</price>
<misc>
<editor id="11N">
<editorBrand>Full Edit</editorBrand>
<editorEmphasis>Full</editorEmphasis>
</editor>
</misc>
</book>
</catalog>
Наш VBA Код:
Sub mySub()
Dim XMLFile As Variant
Dim seriesTitle As Variant
Dim series As String, Author As String, Title As String, StoreLocation As String
Dim ISBN As String, copies As String, storelc As String
Dim seriesArray() As String, AuthorArray() As String, BookTypeArray() As String, TitleArray() As String
Dim StoreLocationArray() As String, ISBNArray() As String, copiesArray() As String
Dim i As Long, x As Long, j As Long, pn As Object, loc As Object, arr, ln As String, loc2 As Object
Dim mainWorkBook As Workbook
Dim n As IXMLDOMNode
Set mainWorkBook = ActiveWorkbook
Set XMLFile = CreateObject("Microsoft.XMLDOM")
XMLFile.Load ("C:\Books.xml")
XMLFile.setProperty "SelectionLanguage", "XPath"
x = 1
j = 0
Set seriesTitle = XMLFile.SelectNodes("/catalog/book/misc/PublishedAuthor/seriesTitle")
For i = 0 To (seriesTitle.Length - 1)
series = seriesTitle(i).Text
storelc = seriesTitle(i).SelectSingleNode("store/copies").Text
If series = "AAA" Or series = "BBB" Then
Set pn = seriesTitle(i).ParentNode
StoreLocation = pn.getElementsByTagName("StoreLocation").Item(0).nodeTypedValue
Author = pn.ParentNode.ParentNode.getElementsByTagName("author").Item(0).nodeTypedValue
Title = pn.ParentNode.ParentNode.getElementsByTagName("title").Item(0).nodeTypedValue
ISBN = pn.ParentNode.ParentNode.getAttribute("ISBN")
Set loc = pn.SelectSingleNode("seriesTitle/store[@id='" & storelc & "']/copies")
If loc Is Nothing Then
arr = Split(storelc, "/")
ln = Trim(arr(UBound(arr)))
Set loc = pn.SelectSingleNode("seriesTitle/store[@id='" & ln & "']/copies")
End If
If Not loc Is Nothing Then
copies = loc.Text
Else
copies = "?"
End If
AddValue seriesArray, series
AddValue AuthorArray, Author
AddValue TitleArray, Title
AddValue StoreLocationArray, StoreLocation
AddValue ISBNArray, ISBN
AddValue copiesArray, copies
j = j + 1
x = x + 1
End If
Next
Range("A3").Resize(j, 1).Value = WorksheetFunction.Transpose(AuthorArray)
Range("B3").Resize(j, 1).Value = WorksheetFunction.Transpose(TitleArray)
Range("C3").Resize(j, 1).Value = WorksheetFunction.Transpose(ISBNArray)
Range("D3").Resize(j, 1).Value = WorksheetFunction.Transpose(seriesArray)
Range("E3").Resize(j, 1).Value = WorksheetFunction.Transpose(StoreLocationArray)
Range("F3").Resize(j, 1).Value = WorksheetFunction.Transpose(copiesArray)
End Sub
'Utility method - resize an array as needed, and add a new value
Sub AddValue(arr, v)
Dim i As Long
i = -1
On Error Resume Next
i = UBound(arr) + 1
On Error GoTo 0
If i = -1 Then i = 0
ReDim Preserve arr(0 To i)
arr(i) = v
End Sub
Моя цель состоит в том, чтобы искать "seriesTitle". Поэтому я специально создаю цикл For, который ищет длину найденных элементов, а затем проанализирует «seriesTitle» вместе с ISBN, StoreLocation, Author, Book Title и копиями.
- Если существует серия Title - это версия 14, то - я хочу распечатать серию Title, ISBN, StoreLocation, Author, Название книги и копии.
- Если seriesTitle НЕ существует - это версия 13, тогда - я хочу только напечатать ISBN, Автор и Название книги.
Но проблема в том, что для каждого «идентификатора книги», который существует, необязательно есть «seriesTitle» - единственное отношение, которое мы можем сделать, это то, что когда «version = 13» нет серийного названия.
- Как бы вы пропустили весь документ, если у вас нет объекта для создания поиска по циклу For? И когда «seriesTitle» не существует, как бы вы продолжаете добавлять элементы в массив ISBN, Author и Book Title?
Благодарим вас за то, что вы преподаете мне с любыми полезными комментариями и предложениями!
Почему бы не начать * с набором узлов и не перечеркнуть их? Казалось бы, это самый простой способ приблизиться к этому: вы можете проверить атрибут версии книги и работать с этим, когда решаете, искать ли узел seriesTitle. –
@TimWilliams У меня была попытка создать цикл For, который искал книги, а затем другой цикл For внутри, который будет фильтровать нужные мне узлы, но в итоге я буквально распечатал цикл цикла x количества книг. – NRH