SelectSingleNode с XPath и несколькими пространствами имен

Я пытаюсь выбрать узел в PowerShell, который существует более одного раза. Я объявил пространства имен и безуспешно пытался выбрать с помощью XPath. Я получаю только NULL.

Я не уверен, что я сделал не так, но я могу выбрать все настройки с помощью

$selectedNode = $xml.SelectSingleNode("//ns:settings[@pass='oobeSystem']", $NSMGR)

но я хочу получить компонент с атрибутом @name="Microsoft-Windows-Shell-Setup". Я пробовал разные способы, но результат всегда NULL.

Фрагмент кода:

$NSMGR = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
#$NSMGR.AddNamespace("ns", $xml.DocumentElement.NamespaceURI) default
$NSMGR.AddNamespace("ns", "urn:schemas-microsoft-com:unattend")
$NSMGR.AddNamespace("xsi", "http://www.w3.org/2001/xmlSchema-instance") 

#first try
$selectedNode = $xml.SelectSingleNode("//ns:settings[@pass='oobeSystem']/component[@name='Microsoft-Windows-International-Core']", $NSMGR)
$selectedNode = $xml.SelectSingleNode("//ns:settings[@pass='oobeSystem']/xsi:component[@name='Microsoft-Windows-International-Core']", $NSMGR)
$selectedNode

#second try
$selectedNode = $xml.SelectSingleNode("//ns:settings[@pass='oobeSystem']", $NSMGR)
$selectedNode = $selectedNode.SelectSingleNode("//ns:component[@name='Microsoft-Windows-Shell-Setup']", $NSMGR) #Edit to MS Shell instead of internal core for my example
$selectedNode

Фрагмент XML:

<?xml version="1.0" encoding="utf-8" ?>
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:ew="urn:schemas-microsoft-com:embedded.unattend.internal.v1">
  <settings pass="specialize">
    <component xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <ComputerName>*</ComputerName>
      <TimeZone>UTC</TimeZone>
    </component>
    <component xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <InputLocale>0407:00000407</InputLocale>
      <UILanguage>en-US</UILanguage>
      <SystemLocale>en-US</SystemLocale>
      <UserLocale>en-US</UserLocale>
      <UILanguageFallback>de-DE</UILanguageFallback>
    </component>
  </settings>
  <settings pass="oobeSystem">
    <component xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <OOBE>
        <ProtectYourPC>3</ProtectYourPC>
        <NetworkLocation>Work</NetworkLocation>
        <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
      </OOBE>
    </component>
    <component xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-Embedded-Core-Settings" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <HideEvaluationWarning>1</HideEvaluationWarning>
    </component>
  </settings>
  <settings pass="windowsPE">
    <component xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
      <SetupUILanguage>
        <UILanguage>en-US</UILanguage>
        <WillShowUI>OnError</WillShowUI>
      </SetupUILanguage>
      <UserLocale>en-US</UserLocale>
      <UILanguage>en-US</UILanguage>
      <InputLocale>0407:00000407</InputLocale>
      <SystemLocale>en-US</SystemLocale>
    </component>
  </settings>
</unattend>

person black    schedule 10.02.2016    source источник
comment
Вы создаете менеджер пространств имен для пространств имен из переменной $xmlNewUnattend, но выбираете узлы из переменной $xml. Ваша вторая попытка отлично сработала для меня, когда я также создал менеджер пространства имен из $xml.   -  person Ansgar Wiechers    schedule 10.02.2016
comment
да, вы правы, я просто уменьшил размер и забыл переименовать $xmlNewUnattend в $xml для моего примера. Хорошо, в этом синтаксисе все правильно, но когда вы пытаетесь выбрать Microsoft-Windows-Shell-Setup вместо внутреннего ядра, он выберет первый узел внутри файла, но я хочу поймать тот, который находится в oobeSystem. Так что моя вторая попытка не работает должным образом   -  person black    schedule 11.02.2016


Ответы (1)


Выберите нужный дочерний узел относительно конкретного родительского узла, например:

$selectedNode = $xml.SelectSingleNode("//ns:settings[@pass='oobeSystem']/ns:component[@name='Microsoft-Windows-Shell-Setup']", $NSMGR)

или вот так:

$parentNode = $xml.SelectSingleNode("//ns:settings[@pass='oobeSystem']", $NSMGR)
$selectedNode = $parentNode.SelectSingleNode("./ns:component[@name='Microsoft-Windows-Shell-Setup']", $NSMGR)

Обратите внимание, что вам нужно использовать пространство имен ns: как для родительского и дочернего узла.

person Ansgar Wiechers    schedule 11.02.2016
comment
Оно работает..! :) я уверен, что пробовал ваш способ раньше, но, возможно, в данный момент была другая проблема, так что это не сработало для меня ... Большое спасибо :) - person black; 11.02.2016
comment
@black Возможно, вы использовали неправильное имя компонента? В вашем первом примере используется имя компонента Microsoft-Windows-International-Core, но компонента с таким именем в узле <settings pass="oobeSystem"> нет. - person Ansgar Wiechers; 11.02.2016
comment
Нет, он есть в полном xmlfile. но я создаю его и использую потом. при создании он добавляет атрибут xlmns=, после чего я смог выбрать этот узел без использования второго ns:. Но это работало только для узлов с xlmns= (‹component name=X ... xlmns=›) в его теге. возможно, это было причиной того, что я был сбит с толку тем, как это работает. Теперь я удаляю все пустые теги xlmns= и использую ваше решение, и оно работает как надо :) - person black; 11.02.2016