2017-02-16 5 views
0

Я действительно пытаюсь манипулировать некоторыми XML в PowerShell, которые мне нужно отправить обратно в веб-службу как тело. Может ли кто-нибудь помочь мне получить 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) 

... следуя совету Ansgar, это моя попытка использования пространства имен. (Пунктирная)

[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 [текст() = '1.2.3.5']") $ test ... ничего не возвращает –

+0

... также, когда я делаю Get-Member on родительский узел, я получаю следующее: Тип: System.Xml.XmlElement # http: //www.vmware.com/vcloud/v1.5#SubnetParticipation –

+0

@DavidHocking Код, который я опубликовал, отлично работает с образцом XML, который вы опубликовали , Если он не работает с вашими живыми данными, ваши данные в реальном времени отличаются от ваших данных образца. Обновите свой XML-образец, чтобы больше походить на ваши живые данные. Выйдя на конечность, я бы заподозрил, что у вас есть пространства имен в исходном XML. –

Смежные вопросы