首页 > 解决方案 > Powershel 追加节点

问题描述

我需要在 xml 文档中再添加 3 个节点。我正在尝试以多种方式解决问题,但不幸的是没有结果我的代码正在完成这项工作,但正在添加一个我不想要的属性:如何重复节点?

 My code:

     function Get-XmlNamespaceManager([ xml ]$XmlDocument, [string]$NamespaceURI = "")

 {
     # If a Namespace URI was not given, use the Xml document's default namespace.
    if ([string]::IsNullOrEmpty($NamespaceURI)) { $NamespaceURI = $XmlDocument.DocumentElement.NamespaceURI }

    # In order for SelectSingleNode() to actually work, we need to use the fully qualified node path along with an Xml Namespace Manager, so set them up.
    [System.Xml.XmlNamespaceManager]$xmlNsManager = New-Object  System.Xml.XmlNamespaceManager($XmlDocument.NameTable)
    $xmlNsManager.AddNamespace("ns", $NamespaceURI)
    return ,$xmlNsManager   # Need to put the comma before the variable name so that PowerShell doesn't convert it into an Object[].
}

  function Get-FullyQualifiedXmlNodePath([string]$NodePath,  [string]$NodeSeparatorCharacter = '.')
  {
    return "/ns:$($NodePath.Replace($($NodeSeparatorCharacter), '/ns:'))"
}

   function Get-XmlNode([ xml ]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
     {

      $xmlNsManager = Get-XmlNamespaceManager -XmlDocument $XmlDocument -NamespaceURI $NamespaceURI
[string]$fullyQualifiedNodePath = Get-FullyQualifiedXmlNodePath -NodePath $NodePath -NodeSeparatorCharacter $NodeSeparatorCharacter

   # Try and get the node, then return it. Returns $null if the node was not found.
   $node = $XmlDocument.SelectSingleNode($fullyQualifiedNodePath, $xmlNsManager)
return $node
}

   function Get-XmlNodes([ xml ]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
   {
    $xmlNsManager = Get-XmlNamespaceManager -XmlDocument $XmlDocument -NamespaceURI $NamespaceURI
[string]$fullyQualifiedNodePath = Get-FullyQualifiedXmlNodePath -NodePath $NodePath -NodeSeparatorCharacter $NodeSeparatorCharacter

   # Try and get the nodes, then return them. Returns $null if no nodes were found.
   $nodes = $XmlDocument.SelectNodes($fullyQualifiedNodePath, $xmlNsManager)
return $nodes
}


   $XmlDocument = Get-ChildItem -Path 'C:\Scripts\Add_Languages\Source\' -Recurse -Include "*.imdi" -File | ForEach-Object{
   [xml]$Xml = Get-Content $_.FullName
    $Keynodes = Get-XmlNodes $Xml -NodePath  "METATRANSCRIPT.Session.MDGroup.Content.Keys"


     $ref = $Xml.METATRANSCRIPT.Session.MDGroup.Content.Keys.Key | Where {$_.Name -eq 'Topic'}
     $Key = $Xml.CreateElement('Key')
     $addAtt = $xml.CreateAttribute("Name")
     $addAtt.Value = "Topic"
     $key.Attributes.Append($addAtt)
     $Keynodes.InsertAfter($Key,$ref)


     $ref = $Xml.METATRANSCRIPT.Session.MDGroup.Content.Keys.Key | Where {$_.Name -eq 'Keyword'}
     $Key = $Xml.CreateElement('Key')
     $addAtt = $xml.CreateAttribute("Name")
     $addAtt.Value = "Keyword"
     $key.Attributes.Append($addAtt)
     $Keynodes.InsertAfter($Key,$ref)

     $xml.Save($_.FullName)

}

这是我的代码的结果:

         <Keys>
          <Key Name="Status">Finished</Key>
          <Key Name="Keyword">Language profile, interview, multilingualism, younger speaker</Key>
          <Key Name="Topic">Language profile</Key>
          <Key Name="Topic" xmlns="" /> # <<<<< This node, it's adding the xmlns="" (i don´t need) i  need only <Key Name="Topic"/>
          <Key Name="Location Address">Kabaroan, Babuyan Claro</Key>
      </Keys>

我需要:

      <Keys>
       <Key Name="Status">Finished</Key>
       <Key Name="Keyword">Language profile, interview, multilingualism, younger speaker</Key>
       <Key Name="Topic">Language profile</Key>
       <Key Name="Topic"></Key>
       <Key Name="Topic"></Key>
       <Key Name="Topic"></Key>
       <Key Name="Location Address">Kabaroan, Babuyan Claro</Key>
     </Keys>

再次感谢您在此问题上的任何帮助。

标签: powershell

解决方案


首先要说的是$XmlDocument = Get-ChildItem可以返回多个既DirectoryInfoFileInfo 对象。您不应将其视为文件夹中单个项目的完整路径字符串。

xml 的路径以.imdi. 是文件夹名称还是您将 xml 文件重命名为具有.imdi扩展名?

接下来,您正在使用Get-XmlNodes我没有的功能。那是来自某个模块吗?

这是未使用该函数的修改后的代码,假设C:\Scripts\Add_Languages\Source\IVB1-20180808_01.imdi不是具有奇怪扩展名的单个 xml 文件的完整路径,而是存储 xml 的文件夹的路径。

$path = 'C:\Scripts\Add_Languages\Source\IVB1-20180808_01.imdi'

# get the first XML FileInfo object from this folder
$XmlFile  = @(Get-ChildItem -Path $path -Filter '*.xml' -File)[0]
[xml]$Xml = Get-Content $XmlFile.FullName -Raw

# the number of new Topic nodes you want to add
$numberOfTopicsToAdd = 3

$Keynodes = $Xml.METATRANSCRIPT.Session.MDGroup.Content.Keys

# get the first 'Key' childnode with attribute "Name=Topic"
# using XPath:
$refNode  = $Keynodes.SelectSingleNode("//Key[@Name='Topic']")
# or using:
# $refNode = @($Keynodes.ChildNodes | Where-Object {$_.LocalName -eq 'Key' -and $_.Name -eq 'Topic'})[0]

# create the new nodes
for ($i = 0; $i -lt $numberOfTopicsToAdd; $i++) {
    $Key = $Xml.CreateElement('Key')
    $addAtt = $Xml.CreateAttribute("Name")
    $addAtt.Value = "Topic"
    [void]$key.Attributes.Append($addAtt)
    [void]$Keynodes.InsertAfter($Key, $refNode)
}

# create a name for the output xml file by prefixing with 'New_'
$outXml = Join-Path -Path $path -ChildPath ('New_{0}' -f $XmlFile.Name)
$xml.Save($outXml)

输出:

<Keys>
  <Key Name="Status">Finished</Key>
  <Key Name="Keyword">Language profile, interview, multilingualism, younger speaker</Key>
  <Key Name="Topic">Language profile</Key>
  <Key Name="Topic" />
  <Key Name="Topic" />
  <Key Name="Topic" />
  <Key Name="Location Address">Kabaroan, Babuyan Claro</Key>
</Keys>

希望有帮助


根据您的评论,我看到的文件夹路径实际上是 xml 文件的完整路径和名称,您所要做的就是将顶行更改为:

# get the content of the XML file
$XmlFile  = Get-Item -Path 'C:\Scripts\Add_Languages\Source\IVB1-20180808_01.imdi'
[xml]$Xml = Get-Content $XmlFile.FullName -Raw

其余代码可以保持不变


推荐阅读