如何将 InsertAfter 与 PowerShell 结合使用

发布于 2024-11-15 23:51:11 字数 1685 浏览 4 评论 0原文

我有一些 xml 文件,我想将一个 xml 文件的内容插入到另一个文件中。我想我应该使用 LastChild 和 InsertAfter 方法来完成此任务。到目前为止它对我不起作用。

这是parent.xml 文件:

<manifest>
  <manifestExecution>
    <assetDetail>
      <fileAsset fileAssetGuid="parentguid1">
    <parentfile1 />
      </fileAsset>
      <fileAsset fileAssetGuid="parentguid2">
    <parentfile2 />
      </fileAsset>
    </assetDetail>
  </manifestExecution>
</manifest>

这是child.xml 文件:

<manifest>
  <manifestExecution>
    <assetDetail>
     <fileAsset fileAssetGuid="childguid1">
    <childfile1 />
     </fileAsset>
    </assetDetail>
  </manifestExecution>
</manifest>

我想要做的是从child.xml 中选择fileAsset 节点并在最后一个之后插入到parent.xml 中Parent.xml 中的 fileAsset 节点。

这是我的测试代码:

$parent = [xml] (Get-Content d:\temp\parent.xml)
$parentnode = $parent.manifest.manifestExecution.assetDetail
$child = [xml] (Get-Content d:\temp\child.xml)
$childnode = $child.manifest.manifestExecution.assetDetail.InnerXml
$parentnode.InsertAfter($childnode, $parentnode.LastChild)

这是我收到的错误消息:

Cannot conversion argument "0", with value: ">”将“System.String”类型的值更改为“System.Xml.XmlNode”类型。 行数:5 字符:24 + $parentnode.InsertAfter <<<<< ($childnode, $parentnode.LastChild) + 类别信息:未指定:(:) [],MethodException + FullQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

我做错了什么?

I have some xml files where I want to insert the contents of one xml file into another. I thought I'd use LastChild and the InsertAfter method to accomplish this. So far it's not working for me.

Here is the parent.xml file:

<manifest>
  <manifestExecution>
    <assetDetail>
      <fileAsset fileAssetGuid="parentguid1">
    <parentfile1 />
      </fileAsset>
      <fileAsset fileAssetGuid="parentguid2">
    <parentfile2 />
      </fileAsset>
    </assetDetail>
  </manifestExecution>
</manifest>

And here is the child.xml file:

<manifest>
  <manifestExecution>
    <assetDetail>
     <fileAsset fileAssetGuid="childguid1">
    <childfile1 />
     </fileAsset>
    </assetDetail>
  </manifestExecution>
</manifest>

What I want to do is select the fileAsset node(s) from child.xml and insert into parent.xml after the last fileAsset node in parent.xml.

Here is my test code:

$parent = [xml] (Get-Content d:\temp\parent.xml)
$parentnode = $parent.manifest.manifestExecution.assetDetail
$child = [xml] (Get-Content d:\temp\child.xml)
$childnode = $child.manifest.manifestExecution.assetDetail.InnerXml
$parentnode.InsertAfter($childnode, $parentnode.LastChild)

Here is the error msg I'm getting:

Cannot convert argument "0", with value: "<fileAsset fileAssetGuid="childguid1"> <childfile1 /></fileAsset>", for "InsertAfter" to type "System.Xml.XmlNode": "Cannot conver
t the "<fileAsset fileAssetGuid="childguid1"><childfile1 /></fileAsset>" value of type "System.String" to type "System.Xml.XmlNode"."
At line:5 char:24
+ $parentnode.InsertAfter <<<< ($childnode, $parentnode.LastChild)
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

揪着可爱 2024-11-22 23:51:11

您需要遍历 $childnode 的子节点,将它们从父节点中删除,然后将它们导入到新的文档上下文中($child$parent$parentnode 之前,code> 是不同的 XmlDocument 实例)。

这会将 $childnode 中的所有 fileAsset 节点追加到 $parentnode 中。

$parent = [xml](get-content d:\temp\parent.xml)
$parentnode = $parent.manifest.manifestexecution.assetdetail
$child = [xml](get-content d:\temp\child.xml)
$childnode = $child.manifest.manifestexecution.assetdetail

while ($childnode.haschildnodes) {
  $cn = $childnode.firstchild
  $cn = $childnode.removechild($cn)
  $cn = $parentnode.ownerdocument.importnode($cn, $true)
  $parentnode.appendchild($cn)
}

幸运的是,这些方法中的大多数都返回相同的 XmlNode 或其新版本,因此 while 循环体可以像这样链接在一起:

$parentnode.appendchild( $parentnode.ownerdocument.importnode( $childnode.removechild( $childnode.firstchild ), $true ))

InsertAfter(newChild) ,referenceChild) 也可以工作,但做法会略有不同,因为它还需要对将在其后插入的节点的引用。

You need to iterate through $childnode's children, remove them from their parent, and import them into the new document context ($child and $parent are different XmlDocument instances) before appending to $parentnode.

This will append all fileAsset nodes from $childnode into $parentnode.

$parent = [xml](get-content d:\temp\parent.xml)
$parentnode = $parent.manifest.manifestexecution.assetdetail
$child = [xml](get-content d:\temp\child.xml)
$childnode = $child.manifest.manifestexecution.assetdetail

while ($childnode.haschildnodes) {
  $cn = $childnode.firstchild
  $cn = $childnode.removechild($cn)
  $cn = $parentnode.ownerdocument.importnode($cn, $true)
  $parentnode.appendchild($cn)
}

Fortunately, most of these methods return the same XmlNode or a new version of it, so the body of the while loop could chained together like this:

$parentnode.appendchild( $parentnode.ownerdocument.importnode( $childnode.removechild( $childnode.firstchild ), $true ))

InsertAfter(newChild,referenceChild) could also work, but would be done a little differently since it also needs a reference to the the node that it will be inserted after.

独孤求败 2024-11-22 23:51:11

你的第一个问题是你没有得到一个 XML 元素,而是一个字符串。您需要从 XML 文档中获取 XML 节点,但您使用的速记方法猜测您需要一个字符串。通常,您可以通过将其显式转换为 [System.Xml.XmlElement] 来强制执行此操作,但这并不总是有效。您可以使用“SelectSingleNode”可靠地获取元素。

您还没有解决第二个问题,但它就在眼前。一旦获得 XML,它仍然无法工作,因为它来自不同的 XML 文档,因此您需要“导入”节点。您需要对此进行调整以使 XML 与您设想的方式保持一致,但代码可以正常工作。

$parentString = @"
<manifest>
  <manifestExecution>
    <assetDetail>
      <fileAsset fileAssetGuid="parentguid1">
    <parentfile1 />
      </fileAsset>
      <fileAsset fileAssetGuid="parentguid2">
    <parentfile2 />
      </fileAsset>
    </assetDetail>
  </manifestExecution>
</manifest>
"@
$childString = @"
<manifest>
  <manifestExecution>
    <assetDetail>
     <fileAsset fileAssetGuid="childguid1">
    <childfile1 />
     </fileAsset>
    </assetDetail>
  </manifestExecution>
</manifest>
"@

$parent = [xml] ($parentString)
$parentnode = $parent.manifest.manifestExecution.assetDetail
$child = [xml] ($childString)
$xpath = '/manifest/manifestExecution/assetDetail'
$childnode = $child.SelectSingleNode($xpath)
Write-Host("So the child is $($childnode.OuterXML)")
$importedNode = $parent.ImportNode($childNode,$true)
Write-Host("And after importing: $($importedNode.OuterXML)")
$parentnode.InsertAfter($importednode, $parentnode.LastChild)
Write-Host("To finally yield: $($parent.OuterXML)")

此外,您可能会发现,如果您正确地将其转换为 XmlElement,则可以使用类似于原始代码的内容。

$childnode = [System.Xml.XmlElement]$child.manifest.manifestExecution.assetDetail.InnerXml

your first problem is that you're not getting an XML element, but a string. You need to get an XML node from your XML document, but the shorthand method you're using is guessing you want a string. Usually you can force it by explicitly casting it over to [System.Xml.XmlElement], but that doesn't always work. You can reliably get an element using "SelectSingleNode".

You've not hit your second problem yet, but it's just around the corner. Once you've got XML, it still won't work because it's from a different XML document, so you need to "Import" the node. You'll want to tweak this to get the XML to align the way you envision, but the code works.

$parentString = @"
<manifest>
  <manifestExecution>
    <assetDetail>
      <fileAsset fileAssetGuid="parentguid1">
    <parentfile1 />
      </fileAsset>
      <fileAsset fileAssetGuid="parentguid2">
    <parentfile2 />
      </fileAsset>
    </assetDetail>
  </manifestExecution>
</manifest>
"@
$childString = @"
<manifest>
  <manifestExecution>
    <assetDetail>
     <fileAsset fileAssetGuid="childguid1">
    <childfile1 />
     </fileAsset>
    </assetDetail>
  </manifestExecution>
</manifest>
"@

$parent = [xml] ($parentString)
$parentnode = $parent.manifest.manifestExecution.assetDetail
$child = [xml] ($childString)
$xpath = '/manifest/manifestExecution/assetDetail'
$childnode = $child.SelectSingleNode($xpath)
Write-Host("So the child is $($childnode.OuterXML)")
$importedNode = $parent.ImportNode($childNode,$true)
Write-Host("And after importing: $($importedNode.OuterXML)")
$parentnode.InsertAfter($importednode, $parentnode.LastChild)
Write-Host("To finally yield: $($parent.OuterXML)")

Also, you may find you can use something like your original code if you cast it to XmlElement properly.

$childnode = [System.Xml.XmlElement]$child.manifest.manifestExecution.assetDetail.InnerXml
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文