PowerShell modifications de retour de type de l'objet
Je suis à l'aide de PowerShell v3 et le Windows PowerShell ISE. J'ai la fonction suivante qui fonctionne très bien:
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
}
Maintenant, je vais créer quelques fonctions similaires, de sorte que j'ai envie de casser les 3 premières lignes dans une nouvelle fonction, de sorte que je n'ai pas de copier-coller partout, donc j'ai fait ceci:
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
}
Le problème est que lorsque "return $xmlNsManager" exécute l'erreur suivante est générée:
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Xml.XmlNamespaceManager".
Donc, même si j'ai explicitement exprimés mon $xmlNsManager variables de type Système.Xml.XmlNamespaceManager, quand il revient de l'Obtenir-XmlNamespaceManager fonction PowerShell est de le convertir à un tableau d'Objets.
Si je n'ai pas convertir explicitement la valeur renvoyée par le XmlNamespaceManager fonction du Système.Xml.XmlNamespaceManager, l'erreur suivante est générée à partir de l' .SelectSingleNode (), car le mauvais type de données est transmis à la fonction du 2ème paramètre.
Cannot find an overload for "SelectSingleNode" and the argument count: "2".
Pour une raison PowerShell n'est pas de maintenir le type de données de la variable de retour. Je voudrais vraiment obtenir ce travail à partir d'une fonction, de sorte que je n'ai pas de copier-coller ces 3 lignes dans tous les sens. Toutes les suggestions sont les bienvenues. Merci.
Select-Xml
applet de commande? En utilisant les espaces de noms avec elle, c'est aussi simple que de la transmettre d'une table de hachage de préfixe d'espace de noms mappages par exemple $xml | Select-Xml -XPath '//dns:foo' -namespace @{dns='http://schema.foo.org'}
Merci Keith, en fait, je n'avais pas entendu parler de l'Sélectionnez Xml, applet de commande. Je préfère ignorer l'espace de Noms Xml, tous ensemble, que je ne m'inquiète pas à ce sujet, mais, malheureusement .SelectSingleNode() l'exige, comme je l'ai discuter dans mon blog (blog.danskingdom.com/...). En utilisant Sélectionnez-Xml contourner ce problème?
Select-Xml
est juste l'appel de l'une SelectSingleNode
ou SelectNodes
(XmlDocument) sous les couvertures, donc il est toujours sensibles à des espaces de noms XML qui est pourquoi @Keith utilisé le -namespace
paramètre.Par la façon dont il EST une façon d'ignorer les espaces de noms XML au total, il vous suffit d'écrire votre Xpath différemment. Ce DONC, la question montre comment.
OriginalL'auteur deadlydog | 2013-07-06
Vous devez vous connecter pour publier un commentaire.
Ce qui se passe est PowerShell est la conversion de votre espace de noms de l'objet gestionnaire d'un tableau de chaînes.
Je pense que cela a à voir avec PowerShell est la nature de "dérouler" les collections lors de l'envoi d'objets dans le pipeline. Je pense que PowerShell va le faire pour tout type de mise en œuvre de IEnumerable (a une méthode GetEnumerator).
Comme un travail, vous pouvez utiliser la virgule astuce pour éviter ce problème et d'envoyer l'objet en tant qu'ensemble de la collection.
return
est pas vraiment nécessaire dans ce cas (dernière ligne de la fonction, donc pas besoin pour le retour précoce).Merci pour l'explication, les gars. Keith, je suis habituellement un C# et .Net programmeur qui a récemment obtenu en PowerShell, donc j'ai encore l'habitude de l'aide au retour; j'aime aussi qu'elle rend explicite/évident que la fonction est de retour en arrière.
Un autre gotcha (en plus de ce déroulage de la chose), c'est que tout ce qui renvoie une valeur qui n'est pas définie à une variable ou les canalisations de la valeur null sera retourné à partir de votre fonction, par exemple si vous appelez XmlDocument.AppendChild de la méthode, il sera de retour un objet XmlNode qui sera envoyée avec votre espace de noms de l'objet gestionnaire, à moins que vous en empêcher.
C'est pourquoi j'ai l'habitude d'éviter de retour, sauf quand j'ai besoin de la caution au début sur une fonction. Même alors, j'ai tendance à ne pas utiliser le
return <expr>
forme. Il donne un faux sentiment de ce qui est retourné par la fonction.Vous pouvez aussi jeter à vide pour supprimer la sortie à partir d'une méthode ou d'Applet de commande, c'est à dire
[void] $xmlNsManager.AddNamespace("ns", $NamespaceURI)
.OriginalL'auteur Andy Arismendi
Plus précisément, ce qui se passe ici, c'est que votre code habitude de fortement tapant $fullyQualifiedModePath essaie de tourner la suite de l'Obtenir (qui est une liste d'objets) dans une chaîne.
[string]$foo
permettra de contraindre la variable $foo d'être seulement une chaîne de caractères, peu importe ce qui est venu de l'arrière. Dans ce cas, votre type de contrainte est ce qui est subtilement vissage de le retourner et de le rendre Object[]
Aussi, en regardant ton code, je serais personnellement vous recommandons l'utilisation de Select-Xml (intégré dans la V2 et plus tard), plutôt que de faire beaucoup de main-codées en XML dérouler. Vous pouvez faire de l'espace de noms des requêtes Select-Xml avec l'espace de Noms @{x="..."}.
$fullyQualifiedModePath
ligne n'est pas celui qu'il a du avoir un problème avec. C'est[System.Xml.XmlNamespaceManager]$xmlNsManager =
OriginalL'auteur Start-Automating