无法使用PowerShell加载XML文档

时间:2010-01-05 09:48:58

标签: xml powershell

不知何故,我无法在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>

2 个答案:

答案 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将避免逐行读取文件。

希望这有帮助