xml - 使用 powershell 解析 XML 会给出“需要命名空间管理器或 XsltContext”错误
问题描述
我正在尝试使用 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
我正在尝试将“MaximumCheckForScheduleAttempts”值设置为 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 中的一个简单错字 - 您的 close
</DpoSettings>
与您的 opening 不匹配<RubySettings>
。第二个问题是在 xml 文档中定义的名称空间前缀(例如,来自您的元素的
a
前缀)不会被导入到您的代码中。换句话说,除非您做一些额外的工作来重新定义代码中的前缀,否则您的 in your在 XPath 查询中没有任何意义。xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
<Settings>
a:
a:KeyValueOfstringstring
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 问题的一部分 - 即您需要RubySettings
在 XPath 中包含根才能找到Settings
节点,并使用适当的前缀。
那是:
$ScheduleMaintenance = 'x:RubySettings/x:Settings/a:KeyValueOfstringstring'
此时,您可以使用 XPath 做一些巧妙的事情来找到Key
带有 text 子元素的单个节点MaximumCheckForScheduleAttempts
:
$ScheduleMaintenance = "x:RubySettings/x:Settings/a:KeyValueOfstringstring/a:Key[text()='MaximumCheckForScheduleAttempts']/.."
但where-object
在所有a:KeyValueOfstringstring
节点上使用 PowerShell 可能更容易:
$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)
希望这可以帮助。
推荐阅读
- python - Opencv 相机校准用于世界查看端口映射
- r - 如何将R脚本转换为函数
- java - 从不包含它的模块(jar)中读取的包
- azure-devops - 为继承的进程预定义工作项并在 Azure Boards 中自动创建它
- c++ - QTabWidget setCurrentIndex 未按预期工作
- java - 测试在返回 Void 的方法内的变量上调用了方法
- sql - 如何确定不在 DBA_TAB_PRIVS 表中的用户的表权限?
- mysql - 我可以将多个 MySQL 行组连接到一个字段中吗?
- python - 如何通过创建自己的函数来比较两个变量?
- version-control - 确定用于在 perforce 中提交新更改的更改列表