Невозможно l oop XML, используя Xpath, используя Powershell - PullRequest
1 голос
/ 18 марта 2020

Не могу понять, почему мой простой xpath не работает на следующих XML.

Мне нужно найти узел "развертывание" и удалить дочерний узел, а затем добавить новый дочерний узел. Должно быть довольно просто, но нет, с XML есть что-то, что не позволяет моему коду найти узел развертывания, просто выбрав его по его имени.

XML (Clickonce. Net XML)

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xrml="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
  <assemblyIdentity name="PublishDev.app" version="3.1.0.182" publicKeyToken="38f29cb66cf790f2" language="neutral" processorArchitecture="x86" xmlns="urn:schemas-microsoft-com:asm.v1" />
  <description asmv2:publisher="KLP" asmv2:product="PublishDev" xmlns="urn:schemas-microsoft-com:asm.v1" />
  <deployment install="true">
    <subscription>
      <update>
        <expiration maximumAge="0" unit="days" />
      </update>
    </subscription>
    <deploymentProvider codebase="http://nrs.dev/NrsClient/PublishDev.application" />
  </deployment>
  <compatibleFrameworks xmlns="urn:schemas-microsoft-com:clickonce.v2">
    <framework targetVersion="4.7" profile="Client" supportedRuntime="4.0.30319" />
    <framework targetVersion="4.7" profile="Full" supportedRuntime="4.0.30319" />
  </compatibleFrameworks>
  <dependency>
    <dependentAssembly dependencyType="install" codebase="ApplicationFiles\PublishDev_3_1_0_182\PublishDev.exe.manifest" size="48466">
      <assemblyIdentity name="PublishDev.exe" version="3.1.0.182" publicKeyToken="38f29cb66cf790f2" language="neutral" processorArchitecture="x86" type="win32" />
      <hash>
        <dsig:Transforms>
          <dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
        </dsig:Transforms>
        <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
        <dsig:DigestValue>zbbwOLiL12PznwEX7G3FGhmU8R0=</dsig:DigestValue>
      </hash>
    </dependentAssembly>
  </dependency>
</asmv1:assembly>

Затем до l oop XML с использованием Powershell

function loopXml{
    param(
        $nodes
    )
    write-host "*************************  Loop my xml********************* "
    foreach ($node in $nodes) {
        Write-host $node.toString()
    }
}

$deployManifestFullPath = "D:\temp\stripped.xml"

$sourcexml = [xml](get-content $deployManifestFullPath);
$nodes = $sourcexml.SelectNodes("deployment")
loopXml $nodes 

$nodes = $sourcexml.SelectNodes("//*", $ns)
loopXml $nodes 

Вывод

*************************  Loop my xml*********************
*************************  Loop my xml*********************
assembly
assemblyIdentity
description
deployment
subscription
update
expiration
deploymentProvider
compatibleFrameworks
framework
framework
dependency
dependentAssembly
assemblyIdentity
hash
Transforms
Transform
DigestMethod
DigestValue

Я не понимаю, почему строка

$nodes = $sourcexml.SelectNodes("deployment")

не возвращает узел развертывания. Когда я выбираю весь документ, он там, но ... ну, нужна помощь, чтобы разобраться с этим.

Реф. w3schools XPath Syntax просто добавив имя узла, следует выбрать все узлы с этим именем. В моем случае один узел называется развертыванием.

Ответы [ 2 ]

2 голосов
/ 18 марта 2020

Попробуйте изменить

$nodes = $sourcexml.SelectNodes("deployment")

на

$nodes = $sourcexml.SelectNodes("//*[name()='deployment']")
0 голосов
/ 18 марта 2020

InvalidArgument: Невозможно преобразовать значение «System.Object []» в тип «System. Xml .XmlDocument». Ошибка: «Произошел неожиданный конец файла. Следующие элементы не закрыты: asmv1: сборка. Строка 40, позиция 14».

Вам не хватает чего-то подобного в нижней части xml:

</asmv1:assembly>

Если вы правильно сделали отступ $sourcexml.save('stripped.xml'), вы увидите, что развертывание не является узлом верхнего уровня. Есть также проблема пространства имен.

Вы можете получить $nodes таким образом. Здесь только один. Я не знаю пространства имен:

$nodes = $sourcexml.assembly.deployment
$nodes 


install subscription deploymentProvider
------- ------------ ------------------
true    subscription deploymentProvider

Хм, это работает:

select-xml asmv1:assembly stripped.xml -Namespace @{asmv1='urn:schemas-microsoft-com:asm.v1'}


Node     Path                           Pattern
----     ----                           -------
assembly /Users/js/foo/stripped.xml     asmv1:assembly

Но не это:

select-xml '//deployment' stripped.xml -Namespace @{asmv1='urn:schemas-microsoft-com:asm.v1'} 

Тьфу. Это работает. x может быть чем угодно. Это не может быть xmlns.

select-xml '//x:deployment' stripped.xml -Namespace @{x='urn:schemas-microsoft-com:asm.v2'}  


Node       Path                           Pattern
----       ----                           -------
deployment /Users/js/foo/stripped.xml     //x:deployment

И, наконец, версия selectnodes () с пространством имен. Вам нужно // для поиска подузлов, потому что развертывание не является узлом верхнего уровня. Наличие пространства имен делает его более сложным. x представляет здесь пространство имен по умолчанию.

[System.Xml.XmlNamespaceManager]$nsmgr = $sourcexml.NameTable
$nsmgr.AddNamespace('x','urn:schemas-microsoft-com:asm.v2')
$nodes = $sourcexml.selectnodes('//x:deployment', $nsmgr)
$nodes


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