【问题标题】:Is it possible to define two "SelectSingleNodes" statements while searching for a specific XML entry?是否可以在搜索特定 XML 条目时定义两个“SelectSingleNodes”语句?
【发布时间】:2018-04-17 03:52:40
【问题描述】:

是否可以定义两个“SelectSingleNode”语句同时缩小对特定 XML 值的搜索范围?

我的XML结构如下:

<beans>
  <bean id="MenuGet">
    <property name="name">
    <property name="MapOverride">
      <map>
          <entry key="node.infoblock" value="k4jk2jb54B$T45bt2j5ktb3B%$">
      </map>
    </property>
  </bean>
</beans>

<beans>
  <bean id="SystemGet">
    <property name="name">
    <property name="MapOverride">
      <map>
          <entry key="node.infoblock" value="b34t34bhj54b%B#Y$%Bn45ht5h">
      </map>
    </property>
  </bean>
</beans>

我用来调用我试图从第一个“bean”标签中提取的值的语句如下,但我不确定它是否正确或是否有效:

$statement=$XMLFile.beans.bean.SelectSingleNode("id[contains(@key="Menu")]").property[1].map.SelectSingleNode("entry[@key='node.infoblock ']").值

【问题讨论】:

    标签: powershell


    【解决方案1】:

    该文件中有两个带有键“node.infoblock”的条目。如果您希望每个 bean 有一个条目,那么您不应该使用 SelectSingleNode。使用 SelectNode 获取它们更有意义。

    第二,你发布的xml文件因为格式问题(没有根节点,很多未闭合的标签)无法解析。它应该是这样的:

    <beans>
      <bean id="MenuGet">
        <property name="name" />
        <property name="MapOverride">
          <map>
              <entry key="node.infoblock" value="k4jk2jb54B$T45bt2j5ktb3B%$" />
          </map>
        </property>
      </bean>
      <bean id="SystemGet">
        <property name="name" />
        <property name="MapOverride">
          <map>
              <entry key="node.infoblock" value="b34t34bhj54b%B#Y$%Bn45ht5h" />
          </map>
        </property>
      </bean>
    </beans>
    

    如果您保存该文件,则可以运行此代码检索条目:

    $xmlFilePath = "c:\temp\file.xml"
    $doc = new-object System.Xml.XmlDocument
    $doc.load($xmlFilePath)
    $entries = $doc.SelectNodes("//entry[@key='node.infoblock'][1]")
    foreach($entry in $entries)
    {
        Write-Host $entry.value
    }
    

    打印出来:

    k4jk2jb54B$T45bt2j5ktb3B%$

    b34t34bhj54b%B#Y$%Bn45ht5h

    【讨论】:

    • 太棒了!没想到走那条路。
    【解决方案2】:

    一个单个 XPath 查询,因此单个.SelectSingleNode() 调用可以做你想做的事

    $query = '/*/beans/bean[contains(@id,"Menu")]/property/map/entry[@key="node.infoblock"]'
    $XMLFile.SelectSingleNode($query).value
    

    以上产生k4jk2jb54B$T45bt2j5ktb3B%$

    注意:
    - 要匹配多个节点,只需使用.SelectNodes() 代替.SelectSingleNode();有关使用 Select-Xml cmdlet 的替代方法,请参阅下一节。
    - 该命令假定您的 XML 输入是格式正确的,但它目前不是(缺少根元素,缺少一些结束标签);因为根元素名称未知,所以查询以/*/ 开头。


    替代方案:使用Select-Xml cmdlet

    Select-Xml 本质上包装了 .NET .SelectNodes() 方法并添加了处理多个输入的能力以及直接通过路径定位 XML 文件的能力:

    $query = '/*/beans/bean[contains(@id,"Menu")]/property/map/entry[@key="node.infoblock"]'
    (Select-Xml -LiteralPath file.xml -XPath $query).Node.value
    

    注意需要访问中间的.Node 属性,因为Select-Xml 将结果包装在[Microsoft.PowerShell.Commands.SelectXmlInfo] 实例中。


    至于你尝试了什么:

    如果您仍然调用.SelectSingleNode()(即,如果您使用 XPath),最好通过 XPath 查询定位目标节点 -通过直接在您的 document 对象上调用 .SelectSingleNode() $XMLFile - 并将 PowerShell 的点符号的使用限制为该调用的 result - 通过访问 .value属性作为属性。

    请参阅我的this answer,了解点符号和Select-Xml 使用的比较

    【讨论】:

    • 是否有任何好的资源来学习 Powershell 如何与 XML 或 JSON 文件交互?好像没有那么多覆盖它。
    • @murkywaters:关于 XML:请查看我的更新,希望能帮助您入门; re JSON:在 PowerShell 中对 JSON 的支持非常简单;所以阅读ConvertFrom-JsonConvertTo-Json 帮助主题可能就是您所需要的。
    猜你喜欢
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多