首先,我想引用this,因为它是基于PowerShell脚本进行微小修改的。
修改后的脚本(如下所示)的目标是遍历文件夹中的每个XML,如果它在对象中有一个对象,源文件以.eps结尾,则删除对象及其中的所有内容。从上面引用的链接,看起来好像我必须确保属性中的所有对象都被考虑在内。我试图使用通配符,当我运行它时,它没有弹出任何错误,但是,它也没有删除次要对象标记。
以下是对象/对象的示例XML:
<object class="graphic svg eps file_name:AR1.svg name:AR1" data="sample.svg" height="100" type="image/svg+xml" width="100">
<object class="graphic svg eps file_name:AR1.eps name:AR1" data="sample.eps" height="400" type="application/postscript" width="400">
<p>NONE</p>
</object>
</object>
以下是修改:
Get-ChildItem 'C:\test\*.xml' | ForEach-Object {
$xml = [xml](Get-Content $_.FullName)
$xml.SelectNodes("//object/object") | Where-Object {
$_.class -eq "*" -and
$_.data -eq "*.eps" -and
$_.height -eq "*" -and
$_.type -eq "application/postscript" -and
$_.width -eq "*"
} | ForEach-Object {
$_.ParentNode.RemoveChildNode($_)
}
$xml.Save($_.FullName)
}
我的印象是通配符仍然有用,并且因为带有通配符的属性是随机的,基于XML文件名和图像文件名,使用通配符最好。
我仍然非常绿色,是PowerShell的新手,但感谢任何帮助。
编辑:
在@TheMadTechnician的帮助下,我已经将脚本更新到下面了!
$items | ForEach-Object {
$xml = [xml](Get-Content $_.FullName)
$xml.SelectNodes("//*[@type='application/postscript']") | %{ $_.parentnode.removechild($_) }
$xml.Save($_.FullName)
答案 0 :(得分:2)
问题是您的Where
声明不起作用。如果你只是运行该命令的第一部分,你可以看到这个:
$xml.SelectNodes("//object/object") | Where-Object {
$_.class -eq "*" -and
$_.data -eq "*.eps" -and
$_.height -eq "*" -and
$_.type -eq "application/postscript" -and
$_.width -eq "*"
}
没有返回任何内容,因为只有其中一个评估为True,而这就是字面上等于你指示的类型
通配符非常棒,但您必须正确使用它们。 -eq
运算符是文字的,不接受通配符。因此,当您$_.class -eq "*"
$true
仅$_.class
时,*
是仅包含-like
的字符串。您可以使用这样的通配符的地方是$xml.SelectNodes("//object[contains(@data,'.eps') and @type='application/postscript']") |
Where-Object {
$_.data -like "*.eps" -and
$_.type -eq "application/postscript"
}|%{$_.parentnode.removechild($_)}
运算符。
$xml.SelectNodes("//object[contains(@data,'.eps') and @type='application/postscript']") | %{ $_.ParentNode.RemoveChild($_) }
这可以通过更好的XPath查询来简化:
[1,2,3,4,5][2,4,6,8,10]
[3,6,9,12,24][6,12,18,24,48]
....]