在VBS文件中使用XPath跳过某些节点

时间:2015-03-19 06:17:51

标签: xml xpath vbscript kml

我希望跳过某些节点,但无法弄明白。我的目标是

  • 遍历KML文件,在第一个[SimpleData name =“POA_2006”]节点处停止并将值写入日志。这一切都很好。
  • 跳转到第一个[coordinates]节点并记录所有坐标。这一切都很好。
  • 现在我希望跳过可能在特定部分/邮政编码中的任何其他[坐标]节点。这不会发生。我该怎么做?

这是我的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)内的第二个[coordinates]节点中的一组坐标填充了自己的位置,其中坐标应该是下一个邮政编码(2006)。那么如何跳过第二个[coordinates]节点呢?我想在我现有的内部对于每个SimpleData循环我需要做一些棘手的事情,例如检测一些常见节点中有多少[坐标]节点,如[outerBoundaryIs]如果有两个类似邮政编码2000我需要将这个数字添加到我的ctr变量。这个逻辑确实有效,因为我可以对此进行硬编码并获得结果,但我有点卡住它动态地执行它。提前感谢您的帮助

更新 - 感谢您的意见。我已从上面的示例KLM文件中删除了不必要的坐标,因此更容易阅读。根据这一变化,按照@MathiasMüller的要求,这里是预期的输出(postCode,然后是第一个协调节点中的内容,然后跳转到下一个邮政编码,然后是这个新邮政编码中第一个协调节点中的内容):

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")

3 个答案:

答案 0 :(得分:0)

目前还不清楚你在问什么,但是如果

set coords = xXML.selectNodes("//base:coordinates")

选择所有base:coordinates元素而不是仅选择第一个元素,使用

set coords = xXML.selectNodes("//base:coordinates[1]")

如果这不起作用,请明确显示您需要的输出,而不是仅仅解释它。

答案 1 :(得分:0)

相对于相应的<coordinates>,使用XPath选择<SimpleData>节点将更可靠,而不是使用索引。例如:

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

答案 2 :(得分:0)

回答我自己的问题道歉。我认为解决方案可能会在我的长篇文章中丢失。谢谢你@ har07带我去this page about XPath expresions。这是我的回答,但我也意识到在循环内部引用我的文档(xXML)并不好。我想知道这种解决方案是否可行。用以下解决方案替换我的初始帖子中的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