Jak czytać o: xml za pomocą PowerShell?

Nov 05 2020

Mam następujący plik xml, ale nie wiem, jak go odczytać za pomocą programu PowerShell. Czy ktoś może pomóc? Dzięki!

Muszę uzyskać wartość adresu URL z programu PowerShell.

<o:OfficeConfig xmlns:o="urn:xxx:xxx:xxx">
<o:services>
<o:service o:name="xxxx">
<o:url>https://xxx.xxx</o:url>
</o:service>
</o:services>
</o:OfficeConfig>

Z góry dziękuję!

Odpowiedzi

2 mklement0 Nov 05 2020 at 14:56

Możesz skorzystać z faktu, że wygodna, oparta na właściwościach adaptacja XML DOM w PowerShell zasadniczo ignoruje przestrzenie nazw, umożliwiając po prostu drążenie w dół do interesującego elementu za pomocą niekwalifikowanych nazw elementów:

([xml] (Get-Content -Raw file.xml)).OfficeConfig.services.service.url

Natomiast XPath na bazie Select-Xmlcmdlet to przestrzenie nazw, a zatem wymaga wyraźnej obsługę przestrzeni nazw - lub obejście poprzez local-name()funkcję, jak pokazano w odpowiedzi Mathias R. Jessen jest .

Jeśli chcesz używać właściwej obsługi przestrzeni nazw - która ostatecznie jest bardziej niezawodna, ale nie zawsze jest konieczna - użyj następujących poleceń:

(
  Select-Xml '//o:url' file.xml -Namespace @{ o='urn:schemas-microsoft-com:office:office' }
).Node.InnerText
  • Zwróć uwagę na potrzebę przekazania tablicy hashtable ( @{ ... }), która deklaruje używane prefiksy przestrzeni nazw i adresy URL, co jest warunkiem wstępnym, aby móc używać prefiksów ( o:w tym przypadku) w zapytaniu XPath.

    • Nazwy przedrostków nie muszą odpowiadać nazwom w oryginale, o ile są zgodne z -Namespaceargumentem i są mapowane na oryginalne adresy URL.
  • Select-Xmlzwraca obiekty opakowujące wokół dopasowanych System.Xml.XmlNodeinstancji, więc .Nodejest wymagany, aby uzyskać dostęp do tych ostatnich, a .InnerTextnastępnie zwraca zawartość tekstową węzła.

    • Na marginesie: ta potrzeba dostępu .Nodejest niewygodna, ponieważ typowym przypadkiem użycia jest dbanie o XmlNodejedyną; Sugestia GitHub nr 13669 ma na celu złagodzenie bólu za pomocą
      -Rawprzełącznika, który zwraca XmlNodebezpośrednio instancje.
1 MathiasR.Jessen Nov 05 2020 at 14:43

Możesz użyć Select-Xml:

$rawXml = @' <o:OfficeConfig xmlns:o="urn:schemas-microsoft-com:office:office"> <o:services> <o:service o:name="GetFederationProvider"> <o:url>https://odc.officeapps.live.com/odc/emailhrd/getfederationprovider</o:url> </o:service> </o:services> </o:OfficeConfig> '@ $urlNode = $rawXml |Select-Xml -XPath '//*[local-name() = "url"]' |Select -Expand Node $url = $urlNode.innerText

$url będzie teraz zawierać ciąg "https://odc.officeapps.live.com/odc/emailhrd/getfederationprovider"

1 AdminOfThings Nov 05 2020 at 15:00

Ponieważ zwracasz json, możesz po prostu przekonwertować z json na obiekt PowerShell:

$configServiceUrl = "https://officeclient.microsoft.com/config16processed?rs=en-us&build=16.0.7612" $headers = @{'Accept' = 'application/json'}
$getFederationProviderEndpoint = Invoke-WebRequest -Uri "$($configServiceUrl)&services=GetFederationProvider" -Headers $headers -Method GET

$obj = $getFederationProviderEndpoint.Content | ConvertFrom-Json
$obj.'o:officeconfig'.'o:services'.'o:service'.'o:url'