2017-02-16 140 views
0

我真的很努力地操纵PowerShell中的一些XML,我需要将它作为一个主体发送回Web服务。任何人都可以帮助我得到XML需要讨论的方式吗?在另一个节点之后插入一个新的XML节点

<?xml version="1.0" encoding="UTF-8"?> 
<EdgeGateway> 
<Configuration> 
    <GatewayInterfaces> 
     <GatewayInterface> 
      <InterfaceType>uplink</InterfaceType> 
      <SubnetParticipation> 
       <Gateway>1.2.3.4</Gateway> 
       <Netmask>255.255.255.240</Netmask> 
       <IpAddress>1.2.3.5</IpAddress> 
# Missing the IpRange XML section - defined below 
       <UseForDefaultRoute>true</UseForDefaultRoute> 
      </SubnetParticipation> 
      <UseForDefaultRoute>true</UseForDefaultRoute> 
     </GatewayInterface> 
    </GatewayInterfaces> 
</Configuration> 
</EdgeGateway> 

需要成为:

<?xml version="1.0" encoding="UTF-8"?> 
<EdgeGateway> 
<Configuration> 
    <GatewayInterfaces> 
     <GatewayInterface> 
      <InterfaceType>uplink</InterfaceType> 
      <SubnetParticipation> 
       <Gateway>1.2.3.4</Gateway> 
       <Netmask>255.255.255.240</Netmask> 
       <IpAddress>1.2.3.5</IpAddress> 
# New Content added here 
       <IpRanges> 
        <IpRange> 
         <StartAddress>1.2.3.5</StartAddress> 
         <EndAddress>1.2.3.5</EndAddress> 
        <IpRange> 
       </IpRanges> 
# End of new content 
       <UseForDefaultRoute>true</UseForDefaultRoute> 
      </SubnetParticipation> 
      <UseForDefaultRoute>true</UseForDefaultRoute> 
     </GatewayInterface> 
    </GatewayInterfaces> 
</Configuration> 
</EdgeGateway> 

到目前为止,我已经能够创造新的内容新的XML节点/元素,但我不能让它在正确的位置插入。我可以使AppendChild()方法起作用,但它会将该内容放在<UseForDefaultRoute>部分之后 - 而不是之前。

我试过做InsertBefore()InsertAfter(),但它只是不想工作。 最后,当我做AppendChild()的方法时,我还得到了一些额外的文本,我没有想到的,关于xmlns的一些?

<IpRanges xmlns=""><IpRange><StartAddress>1.2.3.5</StartAddress><EndAddress>1.2.3.5</EndAddress></IpRange></IpRanges> 

这是我好不容易才拼凑,请记住,它的分解:(

# load XML file 
[xml]$doc = $response 

# create node <StartAddress> 
$startNode = $doc.CreateNode('element', 'StartAddress', '') 
$start = $doc.CreateTextNode('1.2.3.5') 
$startNode.AppendChild($start) | Out-Null 

# create node <EndAddress> 
$endNode = $doc.CreateNode('element', 'EndAddress', '') 
$end = $doc.CreateTextNode('1.2.3.5') 
$endNode.AppendChild($end) | Out-Null 

# create node <IpRange> and append child nodes <StartAddress> and  <EndAddress> 
$ipRange = $doc.CreateNode('element', 'IpRange', '') 
$ipRange.AppendChild($startNode) | Out-Null 
$ipRange.AppendChild($endNode) | Out-Null 

# create node <IpRanges> and append child nodes <IpRange> 
$ipRanges = $doc.CreateNode('element', 'IpRanges', '') 
$ipRanges.AppendChild($ipRange) | Out-Null 

# append node <IpRanges> to node <SubnetParticipation> 
$subnetParticpation = $doc.EdgeGateway.Configuration.GatewayInterfaces.GatewayInterface[1].SubnetParticipation.AppendChild($ipRanges) 

...下面从安斯加尔的意见,这是我在使用一个命名空间的尝试。(破)

[xml]$fragment = "<dummy xmlns:xsi='http://www.vmware.com/vcloud/v1.5'><IpRanges>$($ipRanges.InnerXml)</IpRanges></dummy>" 

# $fragment.InnerXml ..returns.. 
# <dummy xmlns:xsi="http://www.vmware.com/vcloud/v1.5"><IpRanges><IpRange><StartAddress>185.39.247.98</StartAddress><EndAddress>185.39.247.98</EndAddress></IpRange></IpRanges></dummy> 

# $body is the full XML Document I want to paste into 
[xml]$xml = $body 

$nsm = New-Object Xml.XmlNamespaceManager $xml.NameTable 
$nsm.AddNamespace('xsi', $xml.NamespaceURI) 
$node = $xml.ImportNode($fragment.DocumentElement.IpRanges, $true) 

$subnetPart = $xml.SelectSingleNode("//IpAddress[text()='185.39.247.98']", $nsm) 
$subnetPart 

# returns nothing 
+0

“想不工作” 是不够的问题说明。你究竟试过了什么?那次尝试的结果究竟是什么? –

+0

当然,我会在编辑中添加上面的内容,我不想发布大量问题,所以很抱歉,我最终放弃了这一部分。 –

回答

0

考虑XSLT,专用,W3C符合规范的语言,旨在将XML文件到其他的XML,HTML,甚至文本格式。PowerShell中可以调用内置XslCompiledTransform类传入源文件,xslt脚本和输出文件的参数。

XSLT(采用恒等变换复制的是并更新SubnetParticipation节点)

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output version="1.0" encoding="UTF-8" indent="yes" method="xml"/> 
<xsl:strip-space elements="*"/> 

    <!-- Identity Transform --> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="SubnetParticipation"> 
    <xsl:copy> 
     <xsl:apply-templates /> 
     <IpRanges> 
     <IpRange> 
      <StartAddress>1.2.3.5</StartAddress> 
      <EndAddress>1.2.3.5</EndAddress> 
     </IpRange> 
     </IpRanges> 
    </xsl:copy> 
    </xsl:template> 

</xsl:transform> 

PowerShell的

param ($xml, $xsl, $output) 

if (-not $xml -or -not $xsl -or -not $output) { 
    Write-Host "& .\xslt.ps1 [-xml] xml-input [-xsl] xsl-input [-output] transform-output" 
    exit; 
} 

trap [Exception]{ 
    Write-Host $_.Exception; 
} 

$xslt = New-Object System.Xml.Xsl.XslCompiledTransform; 

$xslt.Load($xsl); 
$xslt.Transform($xml, $output); 

Write-Host "generated" $output; 

命令行呼叫(或批处理脚本呼叫)

Powershell.exe -File "C:\Path\To\PowerShell\Script.ps1" 
"C:\Path\To\Source.xml" "C:\Path\To\Transform.xsl" "C:\Path\To\Output.xml" 

输出

<?xml version="1.0" encoding="utf-8"?> 
<EdgeGateway> 
    <Configuration> 
    <GatewayInterfaces> 
     <GatewayInterface> 
     <InterfaceType>uplink</InterfaceType> 
     <SubnetParticipation> 
      <Gateway>1.2.3.4</Gateway> 
      <Netmask>255.255.255.240</Netmask> 
      <IpAddress>1.2.3.5</IpAddress> 
      <UseForDefaultRoute>true</UseForDefaultRoute> 
      <IpRanges> 
      <IpRange> 
       <StartAddress>1.2.3.5</StartAddress> 
       <EndAddress>1.2.3.5</EndAddress> 
      </IpRange> 
      </IpRanges> 
     </SubnetParticipation> 
     <UseForDefaultRoute>true</UseForDefaultRoute> 
     </GatewayInterface> 
    </GatewayInterfaces> 
    </Configuration> 
</EdgeGateway> 
+0

感谢您的建议,它*听起来很有趣,但因为我想从剧本中做所有事情,所以我试着重新写下你发布的内容。我猜这是行不通的,因为.load方法期望从文件系统读取一个项目? - 我不知道如何让它加载XSL。 –

+0

您的XML不是从外部加载的吗?注意XSL *是一个格式良好的XML文件,可以像任何XML一样处理,包括从嵌入字符串读取。啊......再一次,令人敬畏的递归XSLT返回到未被使用,未被重视,基本上被忽略的保险库。我们尝试了PHP,Python,Java,现在的PowerShell板! – Parfait

0

你可以像这样一些其他的节点之后插入新节点:

$node = $doc.SelectSingleNode("//IpAddress[text()='1.2.3.5']") 
$node.ParentNode.InsertAfter($ipRanges, $node) 
+0

每当我使用//表示法时,都无法找到IpAddress节点,从ISE中选择的选择中删除//。 为了让事情对我更加困惑,在真实环境中,在ISE(使用SelectSingleNode)中工作的方法无效(有或没有//),我认为这可能是一个对象类型问题。 $ test = $ body.SelectSingleNode(“// IpAddress [text()='1.2.3.5']”) $ test ...什么都没返回 –

+0

...另外,当我做一个Get-Member父节点,我得到以下 TypeName:System.Xml.XmlElement#http://www.vmware.com/vcloud/v1.5#SubnetParticipation –

+0

@DavidHocking我发布的代码与您发布的示例XML一起工作得很好。如果它不适用于您的实时数据,那么您的实时数据与您的样本数据不同。请更新您的XML示例以更类似于您的实时数据。出门在外,我会怀疑你在原始XML中有名称空间。 –

相关问题