2017-02-16 137 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中有名稱空間。 –

相關問題