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="..."}.