Похоже, у вас есть несколько проблем.
Первая - простая опечатка в вашем образце xml - ваше закрытие </DpoSettings>
не соответствует вашему открытию <RubySettings>
.
Вторая проблема заключается в том, что префиксы пространства имен, определенные в документе xml (например, префикс a
в xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
из вашего элемента <Settings>
), наделены не импортируется в ваш код. Другими словами, a:
в вашем a:KeyValueOfstringstring
не имеет никакого значения в ваших запросах 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'
...
и столько же, сколько префикс в XP Если строка совпадает с той, что в XmlNamespaceManager, все будет работать нормально.
Теперь, когда все это работает, мы можем уточнить запрос XPath, чтобы выбрать узел, который нас интересует.
запрос XPath
Примечание. Приведенный выше код также устраняет одну часть проблемы XPath - т. Е. Вам нужно включить root RubySettings
в XPath, чтобы найти узел Settings
и используйте соответствующие префиксы.
То есть:
$ScheduleMaintenance = 'x:RubySettings/x:Settings/a:KeyValueOfstringstring'
На этом этапе вы можете сделать что-то умное с XPath, чтобы найти единственный узел с дочерним элементом Key
с текстом MaximumCheckForScheduleAttempts
:
$ScheduleMaintenance = "x:RubySettings/x:Settings/a:KeyValueOfstringstring/a:Key[text()='MaximumCheckForScheduleAttempts']/.."
но, вероятно, проще использовать PowerShell where-object
на всех a:KeyValueOfstringstring
узлах:
$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)
Надеюсь, это поможет.