2012-04-25 33 views
2

考慮下面的XML文檔:這個XML管道中的null項是什麼?

$xml = [xml] "<root><value>one</value><value>two</value></root>" 

,然後打印值(與一些前綴/後綴):

$xml.root.value | %{"*$_*"} 
*one* 
*two* 

到目前爲止好。但是,如果元素不存在,則通過管道傳播空項:

$xml.root.foo | %{"*$_*"} 
** 

爲什麼會這樣?有沒有辦法避免這種額外的檢查:

$xml.root.foo | ?{$_} | %{"*$_*"} 

這很容易忘記,它似乎容易出錯。

回答

2

要關閉沉默的失敗上缺少的屬性使用Set-StrictMode -Version Latest例如爲:

PS> $xml = [xml] "<root><value>one</value><value>two</value></root>" 
PS> $xml.root.foo | %{"*$_*"} 
** 
PS> Set-StrictMode -Version Latest 
PS> $xml.root.foo | %{"*$_*"} 
Property 'foo' cannot be found on this object. Make sure that it exists. 
At line:1 char:1 
+ $xml.root.foo | %{"*$_*"} 
+ ~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [], PropertyNotFoundException 
    + FullyQualifiedErrorId : PropertyNotFoundStrict 

注意,這也將趕上對不存在的變量的引用。我強烈建議以這種方式使用Set-StrictMode,因爲它可以節省大型腳本的調試時間。

+0

我明白了。但是,在我的實際使用案例中,這個示例來自元素確實可能會丟失(這不是錯字),並且我想遍歷所有元素,或者在丟失時不做任何事情。除了我的{$ _}過濾器之外,還有更好的方法嗎? – 2012-04-26 00:14:28

+0

使用PowerShell V1/V2中的XML,如果有多個同名的元素,那麼是的,您必須迭代明確性。在PowerShell V3中,這個問題已經得到解決,所以'$ xml.root.value'輸出'one'和'two'。有些人稱這爲自動展開,有些則稱其爲隱式的foreach。 – 2012-04-26 00:25:03

+0

我有V2,$ xml.root.value的迭代工作正常。我唯一的障礙是,當沒有元素時,我需要拋出逆直覺過濾器來防範$ null。 – 2012-04-26 00:35:18

0

Keith是正確的,你正在得到一個無聲的錯誤,它允許null元素沿管道傳播。我也是一個強烈的腳本支持者PowerShell in StrictMode

這裏是我的解決問題的方法(這將StrictMode啓用工作)。

如果你快速獲取會員$ XML,你會看到它是System.Xml.XmlDocument型(後來的元素將是類型System.Xml.XmlElement)。使用的SelectNodes功能,我們可以得到一個的XmlNodeList對於給定的XPath。所以上面可以寫爲示例文件如下:

$xml.SelectNodes("//root/value") | % {"*" + $_.'#text'+ "*"} 

這會給你所需的輸出。

*one* 
*two* 

如果我們開始尋找不存在的節點:

$xml.SelectNodes("//root/value") | % {"*" + $_.'#text'+ "*"} 

你將得不到迴應,如預期。