如果他们的子节点元素包含Pdt 1
,我希望下面的脚本输出Pdt3
和123456
,但它不输出任何内容。什么是正确的语法?
我知道问题来自
中的错误标准语法@id='$_.id'
ForEach-Object {
$meta = $xml.SelectSingleNode("//catalogue/produits/produit[@id='$_.id']/metas/meta[@code='$meta_code']")
}
这是整个脚本的一部分:
$xml=[xml]@'
<?xml version="1.0" encoding="iso-8859-1"?>
<catalogue>
<produits>
<produit id="pdt1" libelle="produit 1" cat="PDT">
<metas date="2015.07.24">
<meta code="123456" value="123456"></meta>
<meta code="789012" value="ghijkl"></meta>
<meta code="345678" value="mnopqr"></meta>
</metas>
</produit>
<produit id="pdt2" libelle="produit 2" cat="PDT">
<metas date="2015.07.24">
<meta code="123456" value="abcdef"></meta>
<meta code="789012" value="ghijkl"></meta>
<meta code="345678" value="mnopqr"></meta>
</metas>
</produit>
<produit id="pdt3" libelle="produit 3" cat="PDT">
<metas date="2015.07.24">
<meta code="123456" value="123456"></meta>
<meta code="789012" value="ghijkl"></meta>
<meta code="345678" value="mnopqr"></meta>
</metas>
</produit>
</produits>
</catalogue>
'@
$meta_code = "123456"
$xml.catalogue.produits.produit | where {$_.cat.startsWith("PDT")} | ForEach-Object {
$meta = $xml.SelectSingleNode("//catalogue/produits/produit[@id='$_.id']/metas/meta[@code='$meta_code']")
if($meta) {Write-Host $_.libelle "in" $meta.code}
}
答案 0 :(得分:2)
如果将$_.id
放在字符串中,PowerShell只会将$_
扩展为其字符串表示形式。 .id
仍然是文字字符串。要在字符串中展开当前对象的id
属性,需要使用子表达式:
"//catalogue/produits/produit[@id='$($_.id)']/metas/meta[@value='$meta_code']"
据说,从它的外观来看,您要选择libelle
属性以字母cat
开头且包含PDT
的产品的<meta>
属性value
属性具有变量$meta_code
中指定值的节点。如果是这种情况,您可以将整个代码压缩为一个XPath expression:
$meta_code = "123456"
$xpath = "//catalogue/produits/produit" +
"[starts-with(@cat,'PDT') and metas/meta/@value='$meta_code']"
$xml.SelectNodes($xpath) | % { '{0} in {1}' -f $_.libelle, $meta_code }
答案 1 :(得分:2)
我认为问题在于您的XQuery字符串:
$meta = $xml.SelectSingleNode("//catalogue/produits/produit[@id='$_.id']/metas/meta[@code='$meta_code']")
PowerShell将$_.id
解释为$_.ToString() + ".id"
,在您的情况下,最终为pdt1.id
。当然,没有节点匹配该id。
相反,将$_.id
包装为表达式$($_.id)
:
$meta = $xml.SelectSingleNode("//catalogue/produits/produit[@id='$($_.id)']/metas/meta[@code='$meta_code']")
或者,更好的是,使用-f
字符串格式运算符:
$xquery = "//catalogue/produits/produit[@id='{0}']/metas/meta[@code='{1}']" -f $_.id,$meta_code
$meta = $xml.SelectSingleNode($xQuery)
您可以完全放弃对SelectSingleNode
的调用,因为您已经在ForEach-Object
脚本块中获得了该节点。您可以找到所需的元节点:
$xml.catalogue.produits.produit |
Where-Object { $_.cat -like 'PDT*' } |
ForEach-Object {
$produit = $_
$meta = $produit.metas.meta | Where-Object { $_.code -eq $meta_code }
if( $meta )
{
Write-Host -Message ('{0} in {1}' -f $produit.libelle,$meta.code)
}
}
答案 2 :(得分:0)
试试这个Xpath - &#34; // produits / poduit / @ id [./ meta [@code =&#39; 123456&#39;]]&#34;