在Powershell中解析XML

在Powershell中解析XML,xml,powershell,text,find,Xml,Powershell,Text,Find,如果我有一个XML文件,如: <?xml version="1.0" encoding="utf-8"?> <package date-created="19/07/2016" version="6" system="6"> <description /> <system /> <res id="1057002654" name="ABC" path="/DEF" type="F" mimeType="application/x-

如果我有一个XML文件,如:

<?xml version="1.0" encoding="utf-8"?>
<package date-created="19/07/2016" version="6" system="6">
  <description />
  <system />
  <res id="1057002654" name="ABC" path="/DEF" type="F" mimeType="application/x-shared">
    <description />
    <keywords />
    <resver id="1057014163" major="1" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" />
    <resver id="1057014677" major="2" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" />
    <resver id="1057015106" major="3" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" />
    <resver id="1057016183" major="4" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" />
    <resver id="1057016374" major="5" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" />
    <resver id="1057017622" major="6" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" />
    <resver id="1057017704" major="7" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" />
    <resver id="1057017863" major="8" minor="0" revision="0" effective-from="20010101000000" effective-to="20991231235959" />
  </res>
</package>
这只是一个快速测试,看看我是否可以达到我想要的位并进行更新,但失败的原因是:

Property 'id' cannot be found on this object; make sure it exists and is settable.
然后我尝试了一些类似的方法:

$xml = [xml](Get-Content 'C:\TEST\package.xml')
$nodes = $xml.SelectNodes("//*[@res]")
foreach ($node in $nodes) {

$node.Attributes | %{$_}  > C:\TEST\disk.txt }
这实际上会将属性中的所有值写入一个.txt文件,但似乎无法找到一种方法来实际执行我想要的操作

/编辑-修改了我的实际意图。以这样的代码结束,其中$Ref是数组$References中的一项

foreach ($Ref in $References)
{
    $xml = [xml](Get-Content 'C:\TEST\package.xml')
    $res = $xml.SelectSingleNode('//res[@id = $Ref]/child::resver')
    $resource = $res.id + ".txt"

    # more stuff here
} 
但是,正在获取此错误:

Exception calling "SelectSingleNode" with "1" argument(s): "Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function."
At C:\TEST\script.ps1:22 char:38
+ [string] $res = $xml.SelectSingleNode <<<< ('//res[@id = $Ref]/child::resver')
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException
使用“1”参数调用“SelectSingleNode”时出现异常:“需要命名空间管理器或XsltContext。此查询具有前缀、变量或用户定义函数。”
在C:\TEST\script.ps1:22 char:38

+[string]$res=$xml.SelectSingleNode在找到具有正确ID的
节点后,使用
父节点::
轴查找相应的父节点:

$path = 'C:\TEST\package.xml'
$myxml = [xml](Get-Content $path)
# Locate resver, select parent res node
$res = $myxml.SelectSingleNode('//resver[@id = "1057014163"]/parent::res')
# Update id
$res.SetAttribute('id','123')
# Save document
$myxml.Save($path)
您还可以为父节点使用
别名:

//resver[@id = "1057014163"]/..
或者,选择具有所述子节点的
res
节点:

//res[resver/@id = "1057014163"]

以另一种方式执行(根据父节点的
id
查找所有
resver
子节点
id
值):


(注意使用
SelectNodes()
而不是
SelectSingleNode()

您应该解析xml,而不是xpath或xquery。fwiw-我可以推荐RegexBuddy来更好地感受regex(不是附属的,而是狂热的用户)。编写xquery只是一个练习(读作:not my cup of tea,抱歉),这不是有效的XML,节点名称本身不能有属性值(并且
=
不允许作为名称的一部分)@LievenKeersmaekers-为这个真正垃圾的问题道歉。我已经完全重构了它,如果您能看一看,我将不胜感激。
$xml.SelectNodes(//res[resver/@id=1057014163]/@id”)
@hshah-真的不需要道歉,我没有任何冒犯的地方:)。你有你的答案(即使我想,我也不能提供),我从中吸取了教训。谢谢;)感谢你和@PetSerAl。已经让我发疯很久了!:)对不起,伙计们,当我意识到自己是个白痴并从另一个角度看问题时,我又补充了一点。我有res id,需要最后一个resver id。我得到了代码,但它给了我错误:(我仍然在使用SelectSingleNode(),因为我只需要最后一个节点:)我想我的错误发生了,因为我试图在SelectSingleNode()中使用一个变量如果你想要变量展开,就用单引号替换双引号
//res[resver/@id = "1057014163"]
$ids = $myxml.SelectNodes('//res[@id = "1057002654"]/resver[@id]') |Select -Expand id