17

PowerShell v3 と Windows PowerShell ISE を使用しています。私は正常に動作する次の機能を持っています:

function Get-XmlNode([xml]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
{
    # 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)

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

ここで、いくつかの同様の関数を作成するので、最初の 3 行を新しい関数に分割して、どこにでもコピー アンド ペーストする必要がないようにしたいので、次のようにしました。

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
}

function Get-XmlNode([xml]$XmlDocument, [string]$NodePath, [string]$NamespaceURI = "", [string]$NodeSeparatorCharacter = '.')
{
    [System.Xml.XmlNamespaceManager]$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
}

問題は、「return $xmlNsManager」を実行すると、次のエラーがスローされることです。

Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Xml.XmlNamespaceManager".

そのため、$xmlNsManager 変数を System.Xml.XmlNamespaceManager 型に明示的にキャストしたとしても、Get-XmlNamespaceManager 関数から返されると、PowerShell はそれをオブジェクト配列に変換しています。

Get-XmlNamespaceManager 関数から返された値を System.Xml.XmlNamespaceManager に明示的にキャストしないと、.SelectSingleNode() 関数から次のエラーがスローされます。関数の 2 番目のパラメーターに間違ったデータ型が渡されているためです。

Cannot find an overload for "SelectSingleNode" and the argument count: "2".

そのため、何らかの理由で PowerShell が戻り変数のデータ型を維持していません。これらの3行をあちこちにコピーして貼り付ける必要がないように、関数からこれを機能させたいと本当に思っています。任意の提案をいただければ幸いです。ありがとう。

4

2 に答える 2

1

より具体的には、ここで起こっていることは、$fullyQualifiedModePath を強く入力するコーディングの習慣が、Get (オブジェクトのリスト) の結果を文字列に変換しようとしていることです。

[文字列]$foo

何が戻ってきても、変数 $foo を文字列のみに制限します。この場合、あなたの型制約は、戻り値を微妙に台無しにしてそれを Object[] にしているものです

また、あなたのコードを見て、手動でコーディングされた XML 展開をたくさん行うよりも、Select-Xml (V2 以降に組み込まれています) を使用することを個人的にお勧めします。-Namespace @{x="..."} を使用して、Select-Xml で名前空間クエリを実行できます。

于 2013-07-06T18:54:56.440 に答える