#excel #xml #vba
#excel #xml #vba
Вопрос:
У меня возникли некоторые проблемы с извлечением узлов, которые указаны ниже, друг другу. Я предпочитаю не выполнять цикл с for each node
через родительские узлы, потому что реальный XML-файл очень большой со многими дочерними узлами. Я надеюсь, что есть другой способ, аналогичный тому, что я уже делаю.
Я хочу распечатать рецепт RECIPE_LABEL_STRING/text()
с внутренними вложенными рецептами SUB_DATA/ID/text()
Проблема в том, что существует несколько рецептов с разными вложенными рецептами, и то, как я это делаю сейчас, я получаю все вложенные рецепты, прикрепленные к родительскому рецепту. Мне нужно «исправить» первый elt
внутри SelecNodes
. Возможно ли это?
Мой код:
Dim wb As Workbook
Set wb = ThisWorkbook
Dim oXMLFile As Object
Set oXMLFile = CreateObject("Microsoft.XMLDOM")
XMLFileName = ("C:UsersxDesktopNodeSearch.xml")
If XMLFileName = "" Then
MsgBox "No XML found"
Exit Sub
Else
End If
If oXMLFile.Load(XMLFileName) Then
'MsgBox "Loaded successfully"
Else
Exit Sub
End If
Set RecipeID = oXMLFile.SelectNodes("/ADEL:Definitions/RecipeCollection/RECIPE_NUMBER/RECIPE_DATA/elt/RECIPE_LABEL_STRING/text()")
Set SubRecipeID = oXMLFile.SelectNodes("/ADEL:Definitions/RecipeCollection/RECIPE_NUMBER/RECIPE_DATA/elt/LAYER_DATA/elt/LAYER_SUB_DATA/SUB_DATA/ID/text()")
Row = 2
For i = 0 To RecipeID.Length - 1
wb.Sheets("Sheet1").Cells(Row, 1) = RecipeID(i).NodeValue
For s = 0 To SubRecipeID.Length - 1
wb.Sheets("Sheet1").Cells(Row, 2) =
SubRecipeID(s).NodeValue
Row = Row 1
Next
Row = Row 1
Next
файл XML:
<?xml version="1.0" encoding="utf-8"?>
<!-- Automatically generated XML file -->
<ADEL:Definitions xmlns:ADEL="http://XMLSchema/MT/TWIN/ADEL/v6.2.1"
xmlns:ADELrap="http://XMLSchema/MT/TWIN/ADEL/v6.2.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" xsi:schemaLocation="http://XMLSchema/MT/TWIN/ADEL/v6.2.1 ADEL.xsd">
<RecipeCollection>
<UnitRecipe></UnitRecipe>
<RECIPE_NUMBER>
<RECIPE_DATA>
<elt>
<RECIPE_LABEL_STRING>Recipe 1</RECIPE_LABEL_STRING>
<LAYER_DATA>
<elt>
<LAYER_SUB_DATA>
<SUB_DATA>
<ID>Sub Recipe 1</ID>
</SUB_DATA>
</LAYER_SUB_DATA>
</elt>
<elt>
<LAYER_SUB_DATA>
<SUB_DATA>
<ID>Sub Recipe 2</ID>
</SUB_DATA>
</LAYER_SUB_DATA>
</elt>
</LAYER_DATA>
</elt>
<elt>
<RECIPE_LABEL_STRING>Recipe 2</RECIPE_LABEL_STRING>
<LAYER_DATA>
<elt>
<LAYER_SUB_DATA>
<SUB_DATA>
<ID>Sub Recipe 1</ID>
</SUB_DATA>
</LAYER_SUB_DATA>
</elt>
<elt>
<LAYER_SUB_DATA>
<SUB_DATA>
<ID>Sub Recipe 2</ID>
</SUB_DATA>
</LAYER_SUB_DATA>
</elt>
<elt>
<LAYER_SUB_DATA>
<SUB_DATA>
<ID>Sub Recipe 3</ID>
</SUB_DATA>
</LAYER_SUB_DATA>
</elt>
</LAYER_DATA>
</elt>
<elt>
<RECIPE_LABEL_STRING>Recipe 3</RECIPE_LABEL_STRING>
<LAYER_DATA>
<elt>
<LAYER_SUB_DATA>
<SUB_DATA>
<ID>Sub Recipe 3</ID>
</SUB_DATA>
</LAYER_SUB_DATA>
</elt>
</LAYER_DATA>
</elt>
</RECIPE_DATA>
</RECIPE_NUMBER>
</RecipeCollection>
</ADEL:Definitions>
Ответ №1:
Попробуйте это решение сверху вниз
Dim RecipeID As Object, SubRecipeID As Object
Set RecipeID = oXMLFile.SelectNodes( _
"/ADEL:Definitions/RecipeCollection/RECIPE_NUMBER/RECIPE_DATA/elt/RECIPE_LABEL_STRING")
With Sheet1 ' using a sheet's Code(Name)
Dim i As Long, r As Long: r = 1
For i = 0 To RecipeID.Length - 1
r = r 1
.Cells(r, 1) = RecipeID(i).Text
' build XPath string starting from RecipeID(i) node's parent :-)
Set SubRecipeID = RecipeID(i).ParentNode.SelectNodes("LAYER_DATA/elt/LAYER_SUB_DATA/SUB_DATA/ID")
Dim ii As Long
For ii = 0 To SubRecipeID.Length - 1
.Cells(r, 2) = SubRecipeID(ii).Text
r = r 1
Next ii
Next
End With
Комментарии:
1. Ага, большое спасибо, это было именно то, что я искал. Я много чего перепробовал, чтобы прикрепить родительские узлы, но никогда бы не понял этого. 🙂