如何使用insertAfter()在XML中的特定元素之后插入元素

时间:2018-02-03 22:27:55

标签: xml powershell parsing element insertafter

我的文件.xml看起来像这样

Client

我想在最后一个设备之后的from django.test import Client from django.urls import reverse client = Client( HTTP_USER_AGENT='Mozilla/5.0', HTTP_REFERER='http://www.google.com', ) response1 = client.get(reverse('foo')) response2 = client.get(reverse('bar')) 中添加一个新设备:

所以我在PowerShell中尝试了以下代码:

<?xml version="1.0" encoding="UTF-8"?>
<layoutMaster xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="..\schema\m.xsd">
  <deviceFamily>
    <deviceFamilyUniqueID>DeviceFamilyWayside_2</deviceFamilyUniqueID>
    <name>DeviceFamilyWayside_2</name>
    <device>SAMSUNG</device>
    <device>SONY</device>
    <deviceFamilyOptions>
      <name>false</name>
    </deviceFamilyOptions>
  </deviceFamily>
  <deviceFamily>
    <deviceFamilyUniqueID>DeviceFamilyWayside_4</deviceFamilyUniqueID>
    <name>DeviceFamilyWayside_4</name>
    <device>IPHONE</device>
    <device>MAC</device>
    <deviceFamilyOptions>
      <name>false</name>
    </deviceFamilyOptions>
  </deviceFamily>
</layoutMaster>

但是我收到了这个错误:

  

无法将参数“1”(值“DeviceFamilyWayside_2”)从“InsertAfter”转换为“System.Xml.XmlNode”:“无法将”System.SamilyWayside_2“值从”System.String“转换为”System“。 Xml.XmlNode“。”

我想得到的最终结果是这样的:

deviceFamily[deviceFamilyUniqueID ='DeviceFamilyWayside_2']

2 个答案:

答案 0 :(得分:2)

在节点<deviceFamilyOptions>之前插入新节点

[xml]$xml = Get-Content -Path $Path

$newNode = $xml.CreateElement("device")
$newNode.InnerText = 'ALCATEL'

$parent = $xml.SelectSingleNode('//layoutMaster/deviceFamily[deviceFamilyUniqueID="DeviceFamilyWayside_2"]')
$ref    = $parent.SelectSingleNode('./deviceFamilyOptions')

$parent.InsertBefore($newNode, $ref) | Out-Null

或者选择最后一个<device>节点作为参考节点,然后插入新节点:

$parent = $xml.SelectSingleNode('//layoutMaster/deviceFamily[deviceFamilyUniqueID="DeviceFamilyWayside_2"]')
$ref    = $parent.SelectSingleNode('./device[last()]')

$parent.InsertAfter($newNode, $ref) | Out-Null

答案 1 :(得分:0)

同样考虑XSLT(兄弟对XPath),这是一种用于转换XML的专用语言。 PowerShell可以使用 System.Xml.Xsl.XslCompiledTransform,扩展名运行XSLT 1.0脚本。

XSLT (另存为.xsl,一个特殊的.xml文件)

<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>

  <!-- Conditionally Update Needed Node -->
  <xsl:template match="deviceFamily[deviceFamilyUniqueID = 'DeviceFamilyWayside_2']">    
     <xsl:copy>        
       <xsl:apply-templates select="deviceFamilyUniqueID|name|device"/>          
       <device>ALCATEL</device>
       <xsl:apply-templates select="deviceFamilyOptions"/>
     </xsl:copy>    
  </xsl:template>

</xsl:transform>

Powershell (任何XML源和XSLT脚本的通用脚本)

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);

命令行

Powershell.exe -File "C:\Path\To\PowerShell\Script.ps1"^
 "C:\Path\To\Input.xml" "C:\Path\To\XSLTScript.xsl" "C:\Path\To\Ouput.xml"

输出 (漂亮的打印缩进)

<?xml version="1.0" encoding="UTF-8"?>
<layoutMaster xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:noNamespaceSchemaLocation="..\schema\m.xsd">
   <deviceFamily>
      <deviceFamilyUniqueID>DeviceFamilyWayside_2</deviceFamilyUniqueID>
      <name>DeviceFamilyWayside_2</name>
      <device>SAMSUNG</device>
      <device>SONY</device>
      <device>ALCATEL</device>
      <deviceFamilyOptions>
         <name>false</name>
      </deviceFamilyOptions>
   </deviceFamily>
   <deviceFamily>
      <deviceFamilyUniqueID>DeviceFamilyWayside_4</deviceFamilyUniqueID>
      <name>DeviceFamilyWayside_4</name>
      <device>IPHONE</device>
      <device>MAC</device>
      <deviceFamilyOptions>
         <name>false</name>
      </deviceFamilyOptions>
   </deviceFamily>
</layoutMaster>

XSL Transform Demo