4

あるxmlファイルの内容を別の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の最後のfileAssetノードの後に​​parent.xmlに挿入することです。

これが私のテストコードです:

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

私は何が間違っているのですか?

4

2 に答える 2

6

に追加する前に、の子を反復処理$childnodeし、それらを親から削除し、新しいドキュメントコンテキスト($childおよび$parent異なるXmlDocumentインスタンス)にインポートする必要があります$parentnode

fileAssetこれにより、からのすべてのノードがに追加$childnodeされ$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)動作する可能性もありますが、挿入されるノードへの参照も必要になるため、少し異なる方法で実行されます。

于 2011-06-17T00:46:21.677 に答える
0

最初の問題は、XML要素ではなく、文字列を取得していることです。XMLドキュメントからXMLノードを取得する必要がありますが、使用している簡略化された方法では、文字列が必要であると推測しています。通常、[System.Xml.XmlElement]に明示的にキャストすることで強制できますが、常に機能するとは限りません。「SelectSingleNode」を使用して要素を確実に取得できます。

2番目の問題はまだ発生していませんが、もうすぐです。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
于 2011-06-17T00:49:19.680 に答える