XML анализ с использованием powershell выдает ошибку 'Namespace Manager или XsltContext required' - PullRequest
0 голосов
/ 20 января 2020

Я пытаюсь разобрать ниже xml с помощью powershell. Ниже приведен мой код, результаты которого дают

Исключение, вызывающее «SelectSingleNode» с аргументом «1»: «Требуется менеджер пространства имен или XsltContext. Этот запрос имеет префикс, переменную или пользовательский» функция.

Как разобрать XML с помощью скрипта powershell?

Код:

$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>

1 Ответ

1 голос
/ 21 января 2020

Похоже, у вас есть несколько проблем.

  • Первая - простая опечатка в вашем образце 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)

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...