PowerShell изменяет тип возвращаемого объекта

Я использую 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 строки повсюду. Любые предложения приветствуются. Спасибо.

2 ответов


происходит то, что PowerShell преобразует объект диспетчера пространств имен в массив строк.

Я думаю, что это связано с природой PowerShell "разворачивания" коллекций при отправке объектов по конвейеру. Я думаю, что PowerShell сделает это для любого типа, реализующего IEnumerable (имеет метод GetEnumerator).

Как обойти вы можете использовать трюк запятой, чтобы предотвратить это поведение и отправить объект в целом коллекции.

function Get-XmlNamespaceManager([xml]$XmlDocument, [string]$NamespaceURI = "")
{
    ...
    $xmlNsManager.AddNamespace("ns", $NamespaceURI)
    return ,$xmlNsManager
}

более конкретно, здесь происходит то, что ваша привычка кодирования сильно вводить $fullyQualifiedModePath пытается превратить результат Get (который является списком объектов) в строку.

[строка]$foo

будет ограничивать переменную $foo только строкой, независимо от того, что вернулось. В этом случае ваше ограничение типа-это то, что тонко завинчивает возврат и делает его Object[]

кроме того, глядя на ваш код, я бы лично рекомендуется использовать Select-Xml (встроенный в V2 и более поздние версии), а не делать много раскатки вручную XML. Запросы пространства имен можно выполнять в Select-Xml with-Namespace @{x="..."}.