使用 powershell 的 XML 解析'Namespace Manager or XsltContext needed'错误



我正在尝试使用powershell解析以下xml。下面是我的代码,结果给出

使用"1"参数调用"SelectSingleNode"的异常:"需要命名空间管理器或 XsltContext。此查询具有前缀、变量或用户定义的函数。

如何使用Powershell脚本解析此XML?

法典:

$webConfig = "Rubyconf.config"
$XmlObj = New-Object XML
$XmlObj.Load($webConfig)
$ScheduleMaintenance = 'Settings/a:KeyValueOfstringstring'
$Xmlnode = $XmlObj.SelectSingleNode($ScheduleMaintenance)
Write-Output $Xmlnode

我正在尝试将"最大检查计划尝试"值设置为 10。有人可以帮助我吗?

XML 文件

<RubySettings xmlns="http://schemasxxxxxx" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Settings xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:KeyValueOfstringstring>
<a:Key>LiveMaximumNumberParallelModelExecutions</a:Key>
<a:Value>7</a:Value>
</a:KeyValueOfstringstring>        
<a:KeyValueOfstringstring>
<a:Key>ModelCompilationTimeout</a:Key>
<a:Value>00:02:00.0000000</a:Value>
</a:KeyValueOfstringstring>
<a:KeyValueOfstringstring>
<a:Key>MaximumCheckForScheduleAttempts</a:Key>
<a:Value>5</a:Value>
</a:KeyValueOfstringstring>
<a:KeyValueOfstringstring>
<a:Key>ExternalCalloutPermitted</a:Key>
<a:Value>true</a:Value>
</a:KeyValueOfstringstring>
<a:KeyValueOfstringstring>
<a:Key>ExternalCalloutTimeout</a:Key>
<a:Value>00:00:00.2000000</a:Value>
</a:KeyValueOfstringstring>
</Settings>
<lastChanged>2019-12-02T15:36:48.513Z</lastChanged>
</DpoSettings>

看起来你遇到了一些问题。

  • 第一个是示例 xml 中的简单拼写错误 - 您的结束</DpoSettings>与您的开头<RubySettings>不匹配。

  • 第二个问题是 xml 文档中定义的命名空间前缀(例如,<Settings>元素xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"中的a前缀(不会导入到代码中。换句话说,a:KeyValueOfstringstring中的a:在 XPath 查询中没有任何意义,除非您做一些额外的工作来重新定义代码中的a:前缀。

  • 第三,您的 XPath 查询Settings/a:KeyValueOfstringstring有点不稳定

无效的 xml

这是一个简单的解决方法 - 如果我们假设结束元素应该是</RubySettings>我们可以解决这个问题,然后我们可以重现您报告的错误。

<RubySettings xmlns="http://schemasxxxxxx" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
...
</DpoSettings>

成为

<RubySettings xmlns="http://schemasxxxxxx" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
...
</RubySettings>

命名空间前缀

若要修复第二个问题(以及错误消息(,您需要做的是创建一个 XmlNamespaceManager 来定义您自己的命名空间前缀,这些前缀可能(也可能不匹配(原始 xml 文档中的前缀,然后在 XPath 查询中使用这些前缀:

$webConfig = "Rubyconf.config"
$XmlObj = New-Object XML
$XmlObj.Load($webConfig)
# create namespace prefixes
$nametable = new-object System.Xml.NameTable;
$nsmgr = new-object System.Xml.XmlNamespaceManager($nametable);
$nsmgr.AddNamespace("x", "http://schemasxxxxxx");
$nsmgr.AddNamespace("a", "http://schemas.microsoft.com/2003/10/Serialization/Arrays");
# now we can use x: and a:
$ScheduleMaintenance = 'x:RubySettings/x:Settings/a:KeyValueOfstringstring'
# note the $nsmgr parameter which maps "a:" in the xpath query to the actual namespace
# "http://schemas.microsoft.com/2003/10/Serialization/Arrays" in the xml document
$Xmlnode = $XmlObj.SelectSingleNode($ScheduleMaintenance, $nsmgr)
Write-Output $Xmlnode
# Key                                      Value
# ---                                      -----
# LiveMaximumNumberParallelModelExecutions 7

请注意前缀名称a与原始 xml 文档中的名称匹配,但我们可以很容易地说出这样的话:

...
$nametable = new-object System.Xml.NameTable;
$nsmgr = new-object System.Xml.XmlNamespaceManager($nametable);
$nsmgr.AddNamespace("default", "http://schemasxxxxxx");
$nsmgr.AddNamespace("arrays", "http://schemas.microsoft.com/2003/10/Serialization/Arrays");
$ScheduleMaintenance = 'default:RubySettings/default:Settings/arrays:KeyValueOfstringstring'
...

只要 XPath 字符串中的前缀与 XmlNamespaceManager 中的前缀匹配,事情就会正常工作。

现在我们已经完成了所有这些工作,我们可以优化 XPath 查询以选择我们真正感兴趣的节点。

XPath 查询

注意 - 上面的代码还修复了 XPath 问题的一部分 - 即您需要在 XPath 中包含根RubySettings才能找到Settings节点,并使用适当的前缀。

那是:

$ScheduleMaintenance = 'x:RubySettings/x:Settings/a:KeyValueOfstringstring'

此时,您可以使用 XPath 执行一些巧妙的操作,以查找具有带有文本MaximumCheckForScheduleAttempts的子Key元素的单个节点:

$ScheduleMaintenance = "x:RubySettings/x:Settings/a:KeyValueOfstringstring/a:Key[text()='MaximumCheckForScheduleAttempts']/.."

但是在所有a:KeyValueOfstringstring节点上使用PowerShell的where-object可能更容易:

$ScheduleMaintenance = "x:RubySettings/x:Settings/a:KeyValueOfstringstring"
$Xmlnodes = $XmlObj.SelectNodes($ScheduleMaintenance, $nsmgr)
$Xmlnode = $xmlnodes | where-object { $_.Key -eq "MaximumCheckForScheduleAttempts" }

注意 - 我们使用SelectNodes而不是SelectSingleNode,然后使用 PowerShell 筛选结果。

更新值

最后,您可以更新节点的值:

$Xmlnode.Value = "10" # value has to be a string

,然后保存 XML 文档

$XmlObj.Save($newFilename)

希望这有帮助。

最新更新