在 VBS 文件中使用 XPath 跳过某些节点
skip certain nodes using XPath in a VBS file
我想跳过某些节点但无法弄清楚。我的 objective 是
- 遍历 KML 文件,停在第一个 [SimpleData name="POA_2006"] 节点并将值写入日志。这一切都很好。
- 进入第一个 [坐标] 节点并记录所有坐标。这一切都很好。
- 现在我希望跳过可能位于特定 section/postcode 中的任何其他 [坐标] 节点。这没有发生。我该怎么做?
这是我的 KML 文件的精简版:
<?xml version="1.0" encoding="utf-8" ?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document id="root_doc">
<Schema name="postcode" id="postcode">
<SimpleField name="STATE_2006" type="string"></SimpleField>
<SimpleField name="POA_2006" type="string"></SimpleField>
</Schema>
<Folder><name>postcode</name>
<Placemark>
<Style><LineStyle><color>ff0000ff</color></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>
<ExtendedData><SchemaData schemaUrl="#postcode">
<SimpleData name="STATE_2006">1</SimpleData>
<SimpleData name="POA_2006">2000</SimpleData>
</SchemaData></ExtendedData>
<MultiGeometry><Polygon><altitudeMode>relativeToGround</altitudeMode><outerBoundaryIs><LinearRing><altitudeMode>relativeToGround</altitudeMode>
<coordinates>151.20118275199999,-33.873293252 151.201538016</coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><altitudeMode>relativeToGround</altitudeMode><outerBoundaryIs><LinearRing><altitudeMode>relativeToGround</altitudeMode>
<coordinates>151.225379008,-33.855265002 151.22524198400001</coordinates></LinearRing></outerBoundaryIs></Polygon></MultiGeometry>
</Placemark>
<Placemark>
<Style><LineStyle><color>ff0000ff</color></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>
<ExtendedData><SchemaData schemaUrl="#postcode">
<SimpleData name="STATE_2006">1</SimpleData>
<SimpleData name="POA_2006">2006</SimpleData>
</SchemaData></ExtendedData>
<Polygon><altitudeMode>relativeToGround</altitudeMode><outerBoundaryIs><LinearRing><altitudeMode>relativeToGround</altitudeMode><coordinates>151.182640768,-33.891296046 151.18194374399997</coordinates></LinearRing></outerBoundaryIs></Polygon>
</Placemark>
</Folder>
</Document></kml>
而她是VBS文件代码:
function readKLMFileAndWriteToFile2(toFileName, fromFileName)
Dim fso, fPath ,xXML
Set fso = CreateObject("Scripting.FileSystemObject")
fPath = fso.GetAbsolutePathName(fromFileName)
Set xXML = CreateObject("Msxml2.DOMDocument")
xXML.SetProperty "SelectionNamespaces", "xmlns:base=""http://www.opengis.net/kml/2.2"""
xXML.setProperty "SelectionLanguage", "XPath"
xXML.async = False
xXML.load fPath
dim simpleData, coords, ctr
ctr = 0
For Each simpleData In xXML.selectNodes("//base:SimpleData[@name='POA_2006']")
writeLog simpleData.text
set coords = xXML.selectNodes("//base:coordinates")
writeLog coords(ctr).text
ctr = ctr + 1
Next
end function
注意 - 此文件不会以任何方式出错。问题是第一个邮政编码 (2000) 内的第二个 [坐标] 节点中的坐标集将其自身填充到下一个邮政编码 (2006) 的坐标所在的位置。那么如何跳过第二个 [coordinates] 节点呢?我在现有的每个 SimpleData 循环中计算我需要做一些棘手的事情,例如检测一些公共节点(例如 [outerBoundaryIs])中有多少 [coordinates] 节点,如果有两个像邮政编码 2000 我需要将这个数字添加到我的点击率变量。这个逻辑确实有效,因为我可以对此进行硬编码并获得结果,但我有点坚持动态地做它。预先感谢您的帮助
更新 - 感谢您的输入。我已经从上面的示例 KLM 文件中删除了不必要的坐标,以便于阅读。基于此更改,正如@Mathias Müller 所要求的,这里是预期的输出(邮政编码,然后是第一个协调节点中的内容,然后跳转到下一个邮政编码,然后是这个新邮政编码中第一个协调节点中的内容):
2000
151.20118275199999,-33.873293252 151.201538016
2006
151.182640768,-33.891296046 151.18194374399997
set coords = xXML.selectNodes("//base:coordinates[1]") 的建议无效。
我也尝试了建议的 FOR 循环。代码不喜欢(预期对象):
set coord = simpleData.selectSingleNode("./ancestor::base:ExtendedData/following-sibling::base:MultiGeometry//base:coordinates")
不太清楚你在问什么,但是如果
set coords = xXML.selectNodes("//base:coordinates")
选择所有 base:coordinates
个元素而不是只选择第一个元素,使用
set coords = xXML.selectNodes("//base:coordinates[1]")
如果这不起作用,请明确显示您需要的输出,而不是仅仅解释它。
不使用索引,select<coordinates>
节点相对于对应的<SimpleData>
使用XPath会更可靠。例如:
For Each simpleData In xXML.selectNodes("//base:SimpleData[@name='POA_2006']")
writeLog simpleData.text
'select coord based on current simpleData :'
set coord = simpleData.selectSingleNode("./ancestor::base:ExtendedData/following-sibling::base:MultiGeometry//base:coordinates")
writeLog coord.text
Next
很抱歉回答我自己的问题。我认为解决方案可能会在我的长 post 中丢失。谢谢@har07 带我去 this page about XPath expresions。这是我的答案所在,但我也意识到在循环中引用我的文档 (xXML) 并不好。我想知道是否可以通过这种方式解决问题。将我初始 post 中的 for 循环替换为解决方案:
For Each Placemark In xXML.selectNodes("//base:Placemark")
set simpleData = Placemark.selectNodes("//base:SimpleData[@name='POA_2006']")
writeLog simpleData(ctr).text
set coords = Placemark.selectNodes(".//base:coordinates")
writeLog coords(0).text
ctr = ctr + 1
Next
我想跳过某些节点但无法弄清楚。我的 objective 是
- 遍历 KML 文件,停在第一个 [SimpleData name="POA_2006"] 节点并将值写入日志。这一切都很好。
- 进入第一个 [坐标] 节点并记录所有坐标。这一切都很好。
- 现在我希望跳过可能位于特定 section/postcode 中的任何其他 [坐标] 节点。这没有发生。我该怎么做?
这是我的 KML 文件的精简版:
<?xml version="1.0" encoding="utf-8" ?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document id="root_doc">
<Schema name="postcode" id="postcode">
<SimpleField name="STATE_2006" type="string"></SimpleField>
<SimpleField name="POA_2006" type="string"></SimpleField>
</Schema>
<Folder><name>postcode</name>
<Placemark>
<Style><LineStyle><color>ff0000ff</color></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>
<ExtendedData><SchemaData schemaUrl="#postcode">
<SimpleData name="STATE_2006">1</SimpleData>
<SimpleData name="POA_2006">2000</SimpleData>
</SchemaData></ExtendedData>
<MultiGeometry><Polygon><altitudeMode>relativeToGround</altitudeMode><outerBoundaryIs><LinearRing><altitudeMode>relativeToGround</altitudeMode>
<coordinates>151.20118275199999,-33.873293252 151.201538016</coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><altitudeMode>relativeToGround</altitudeMode><outerBoundaryIs><LinearRing><altitudeMode>relativeToGround</altitudeMode>
<coordinates>151.225379008,-33.855265002 151.22524198400001</coordinates></LinearRing></outerBoundaryIs></Polygon></MultiGeometry>
</Placemark>
<Placemark>
<Style><LineStyle><color>ff0000ff</color></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>
<ExtendedData><SchemaData schemaUrl="#postcode">
<SimpleData name="STATE_2006">1</SimpleData>
<SimpleData name="POA_2006">2006</SimpleData>
</SchemaData></ExtendedData>
<Polygon><altitudeMode>relativeToGround</altitudeMode><outerBoundaryIs><LinearRing><altitudeMode>relativeToGround</altitudeMode><coordinates>151.182640768,-33.891296046 151.18194374399997</coordinates></LinearRing></outerBoundaryIs></Polygon>
</Placemark>
</Folder>
</Document></kml>
而她是VBS文件代码:
function readKLMFileAndWriteToFile2(toFileName, fromFileName)
Dim fso, fPath ,xXML
Set fso = CreateObject("Scripting.FileSystemObject")
fPath = fso.GetAbsolutePathName(fromFileName)
Set xXML = CreateObject("Msxml2.DOMDocument")
xXML.SetProperty "SelectionNamespaces", "xmlns:base=""http://www.opengis.net/kml/2.2"""
xXML.setProperty "SelectionLanguage", "XPath"
xXML.async = False
xXML.load fPath
dim simpleData, coords, ctr
ctr = 0
For Each simpleData In xXML.selectNodes("//base:SimpleData[@name='POA_2006']")
writeLog simpleData.text
set coords = xXML.selectNodes("//base:coordinates")
writeLog coords(ctr).text
ctr = ctr + 1
Next
end function
注意 - 此文件不会以任何方式出错。问题是第一个邮政编码 (2000) 内的第二个 [坐标] 节点中的坐标集将其自身填充到下一个邮政编码 (2006) 的坐标所在的位置。那么如何跳过第二个 [coordinates] 节点呢?我在现有的每个 SimpleData 循环中计算我需要做一些棘手的事情,例如检测一些公共节点(例如 [outerBoundaryIs])中有多少 [coordinates] 节点,如果有两个像邮政编码 2000 我需要将这个数字添加到我的点击率变量。这个逻辑确实有效,因为我可以对此进行硬编码并获得结果,但我有点坚持动态地做它。预先感谢您的帮助
更新 - 感谢您的输入。我已经从上面的示例 KLM 文件中删除了不必要的坐标,以便于阅读。基于此更改,正如@Mathias Müller 所要求的,这里是预期的输出(邮政编码,然后是第一个协调节点中的内容,然后跳转到下一个邮政编码,然后是这个新邮政编码中第一个协调节点中的内容):
2000
151.20118275199999,-33.873293252 151.201538016
2006
151.182640768,-33.891296046 151.18194374399997
set coords = xXML.selectNodes("//base:coordinates[1]") 的建议无效。
我也尝试了建议的 FOR 循环。代码不喜欢(预期对象):
set coord = simpleData.selectSingleNode("./ancestor::base:ExtendedData/following-sibling::base:MultiGeometry//base:coordinates")
不太清楚你在问什么,但是如果
set coords = xXML.selectNodes("//base:coordinates")
选择所有 base:coordinates
个元素而不是只选择第一个元素,使用
set coords = xXML.selectNodes("//base:coordinates[1]")
如果这不起作用,请明确显示您需要的输出,而不是仅仅解释它。
不使用索引,select<coordinates>
节点相对于对应的<SimpleData>
使用XPath会更可靠。例如:
For Each simpleData In xXML.selectNodes("//base:SimpleData[@name='POA_2006']")
writeLog simpleData.text
'select coord based on current simpleData :'
set coord = simpleData.selectSingleNode("./ancestor::base:ExtendedData/following-sibling::base:MultiGeometry//base:coordinates")
writeLog coord.text
Next
很抱歉回答我自己的问题。我认为解决方案可能会在我的长 post 中丢失。谢谢@har07 带我去 this page about XPath expresions。这是我的答案所在,但我也意识到在循环中引用我的文档 (xXML) 并不好。我想知道是否可以通过这种方式解决问题。将我初始 post 中的 for 循环替换为解决方案:
For Each Placemark In xXML.selectNodes("//base:Placemark")
set simpleData = Placemark.selectNodes("//base:SimpleData[@name='POA_2006']")
writeLog simpleData(ctr).text
set coords = Placemark.selectNodes(".//base:coordinates")
writeLog coords(0).text
ctr = ctr + 1
Next