使用PowerShell3.0在XML中一个接一个地解析行

时间:2014-08-08 01:43:55

标签: xml powershell powershell-v3.0

我正在尝试使用PowerShell3.0一个接一个地解析xml标记下的内容,但我无法以所需的方式执行此操作。 XML看起来像这样

<entry>
    <path>C:\Users\Admin\Uploads</path> <file>upload.exe</file>
    <path>C:\Users\Admin\Downloads</path><file>download.exe</file>
    <path>C:\Users\Admin\Documents</path><file>log_file.log</file>
</entry>

所需的输出是:

C:\Users\Admin\Uploads
upload.exe
C:\Users\Admin\Downloads
download.exe
C:\Users\Admin\Documents
log_file.log

xml文件的名称是new.xml我使用以下代码在每次迭代中只打印路径及其各自的文件。

$new = Get-Content .\new.xml
$new = [xml]$new
foreach($item in $new.entry){
    $item.path
    $item.file
}

但我得到的输出是:

C:\Users\Admin\Uploads
C:\Users\Admin\Downloads
C:\Users\Admin\Documents
upload.exe
download.exe
log_file.exe

我甚至尝试过像这样编辑XML文件:

<entry>
<details>
    <path>C:\Users\Admin\Uploads</path> <file>upload.exe</file>
</details>
<details>
    <path>C:\Users\Admin\Downloads</path><file>download.exe</file>
</details>
<details>
    <path>C:\Users\Admin\Documents</path><file>log_file.log</file>
</details>
</entry>

然后尝试分别解析路径及其文件但是即使这个剂量也有帮助。我哪里错了?有没有办法可以实际解析一个路径及其各自的文件迭代次数。

2 个答案:

答案 0 :(得分:0)

在您的XML中,pathfile元素之间没有任何关系。它们只是在entry下的同一级别列出。

<entry>
  <path>C:\Users\Admin\Uploads</path>
  <file>upload.exe</file>
  <path>C:\Users\Admin\Downloads</path>
  <file>download.exe</file>
  <path>C:\Users\Admin\Documents</path>
  <file>log_file.log</file>
</entry>

如果要生成所需的输出,可以执行以下操作:

foreach($item in $new.entry.ChildNodes) {
    $item.InnerText
}

但请注意,这很脆弱,输出取决于子节点的顺序。这是不好的做法。您的第二个XML要好得多,因为它清楚地表达了pathfile之间的关系。然后,您可以轻松处理每个details元素:

foreach($d in $new2.entry.ChildNodes){
    echo "The file '$($d.file)' is located at the following path: $($d.path)"
}

答案 1 :(得分:0)

假设您在xml中可能总是拥有相同数量的文件和路径,您可以这样做:

$xml = [xml](gc .\new.xml)
$count = $xml.entry.file.Count
if ($count -ne $xml.entry.path.Count) {
    Write-Warning "Mismatched file and path elements. Found $($xml.entry.path.Count) paths and $count files."
}
for($i = 0; $i -lt $count; $i += 1) {
    $xml.entry.path[$i]
    $xml.entry.file[$i]
}

您的第二个xml更简单,因为结构清晰。你可以这样做:

$xml = [xml](gc .\new2.xml)
$xml.entry.details | foreach { $_.path, $_.file }