无法使用Powershell使用Xpath循环XML


无法理解为什么我的简单xpath不能在下面的XML上工作。

我需要找到节点"deployment"并删除子节点,然后添加一个新的子节点。这应该很容易,但不,XML中有一些东西使我的代码无法通过简单地按名称选择部署节点来找到它。

XML(Clickonce.NetXML(

<?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="ApplicationFilesPublishDev_3_1_0_182PublishDev.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>

然后使用Powershell 循环XML

function loopXml{
param(
$nodes
)
write-host "*************************  Loop my xml********************* "
foreach ($node in $nodes) {
Write-host $node.toString()
}
}
$deployManifestFullPath = "D:tempstripped.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语法只需添加节点的名称就可以选择具有该名称的所有节点。在我的例子中,单个节点命名为deployment。

尝试更改

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

$nodes = $sourcexml.SelectNodes("//*[name()='deployment']")

InvalidArgument:无法将值"System.Object[]"转换为类型"System.Xml.XmlDocument"。错误:"出现意外的文件结尾。以下元素未关闭:asmv1:assembly.Line 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

最新更新