不知何故,我无法在PowerShell脚本中读取结构非常简单的XML文件。 XML文件由“Microsoft Log Parser Toolkit”生成,我想将其内容加载到数据库中。
脚本非常简单:
$datalist=[xml] (gc ".\users.xml");
foreach ($ROW in $datalist.ROOT.ROW) {
Write-host $ROW.CompName;
}
预期输出
User1
User2
但没有打印出来。我见过类似的例子(例如here,他们使用PowerShell来解析stsadm -o enumsites
的输出。
我在这里缺少什么?
users.xml的内容也很简单:
<?xml version="1.0" encoding="ISO-10646-UCS-2" standalone="yes" ?>
<!DOCTYPE ROOT[
<!ATTLIST ROOT DATE_CREATED CDATA #REQUIRED>
<!ATTLIST ROOT CREATED_BY CDATA #REQUIRED>
<!ELEMENT CompName (#PCDATA)>
<!ELEMENT SoftwareName (#PCDATA)>
<!ELEMENT ROW (CompName, SoftwareName)>
<!ELEMENT ROOT (ROW*)>
]>
<ROOT DATE_CREATED="2009-12-30 10:44:23" CREATED_BY="Microsoft Log Parser V2.2">
<ROW>
<CompName>User1</CompName>
<SoftwareName>Adobe Reader 9.0</SoftwareName>
</ROW>
<ROW>
<CompName>User2</CompName>
<SoftwareName>CorelDraw Graphics Suite X4</SoftwareName>
</ROW>
</ROOT>
答案 0 :(得分:3)
这应解决它:
Select-Xml -Xml $datalist -XPath '//ROW' | % { $_.Node.CompName }
编辑:根据MediaAndMicrocode,Where-Object应该用于过滤掉无效值,但在这种情况下,它可以在没有它的情况下工作。
问题在哪里?
有趣的是:
poshdev >[62]: $x.ROOT | select -exp row
Select-Object : Property "row" cannot be found.
At line:1 char:17
+ $x.ROOT | select <<<< -exp row
+ CategoryInfo : InvalidArgument: (:PSObject) [Select-Object], PSArgumentException
+ FullyQualifiedErrorId : ExpandPropertyNotFound,Microsoft.PowerShell.Commands.SelectObjectCommand
CompName SoftwareName
-------- ------------
User1 Adobe Reader 9.0
User2 Corel Photoshop 12
因此,如果无法找到财产,请检查其成员:
$datalist.ROOT | gm
它表明它是字符串和XmlElement的集合。基于这些知识,这可以按预期工作:
$datalist.root[1].row
这意味着,转换为[xml]创建了两个项目:string(可能来自DTD部分)和xml。其他解决方法是从xml中删除DTD部分。
答案 1 :(得分:1)
您不必使用Select-Xml删除DTD部件,只需将其传输到Where-Object即可。当您使用Select-Xml(Select-Xml // *)请求所有节点时,Select-Xml将自动收集所有名称空间:
Select-Xml -Xml $datalist -XPath '//*' |
Where-Object { $_.Node.CompName } |
Foreach-Object { $_.Node.CompName }
您还应该知道,将文件传输到Select-Xml比使用Get-Content读取它要快得多。 Get-Content逐行读取,这对大文件来说可能会非常慢。 dir | Select-Xml将避免逐行读取文件。
希望这有帮助