从Powershell读取XML文件/清单

时间:2017-03-27 17:35:32

标签: xml powershell

这些天我正在学习Powershell,请耐心等待。我试图用PowerShell阅读以下XML清单:

<manifest desc="sql manifest">
  <projects>
    <project project_directory="$/TFS/Main/branch/">
      <files>
        <file filename="Shrink.sql"/>
        <file filename="Users.sql"/>
      </files>
    </project>
    <project project_directory="$/TFS/Main/branch/Pre/">
      <files>
        <file filename="Logins.sql"/>
      </files>
    </project>
    <project project_directory="$/TFS/Main/branch/Post/">
      <files>
        <file filename="Security.sql"/>
      </files>
    </project>
  </projects>
</manifest>

我期待这样的结果:

$/TFS/Main/branch/Shrink.sql
$/TFS/Main/branch/Users.sql
$/TFS/Main/branch/Pre/Logins.sql
$/TFS/Main/branch/Post/Security.sql

你们可以帮我使用PowerShell脚本吗?

$XmlDocument = Get-Content -Path "xmlfile.xml" 

1 个答案:

答案 0 :(得分:1)

如果删除**字符,以下代码应该返回您想要的结果,假设您从与xml文件相同的目录运行命令:

#### More than one directory
$results = @()

[xml]$XmlDocument = Get-Content .\xmlfile.xml

$directoryCount = $XmlDocument.manifest.projects.project.Count
$directoryNames = $XmlDocument.manifest.projects.project.project_directory

for($i = 0 ; $i -lt $directoryCount; $i++)
{
    $files = $XmlDocument.manifest.projects.project[$i].files.file

    foreach($file in $files.filename)
    {
        $results += $directoryNames[$i] + $file
    }
}

return $results

#### Single Directory
$results = @()

[xml]$XmlDocument = Get-Content .\xmlfile.xml

$directoryCount = @($XmlDocument.manifest.projects.project).Count
$directoryNames = $XmlDocument.manifest.projects.project.project_directory

for($i = 0 ; $i -lt $directoryCount; $i++)
{
    $files = $XmlDocument.manifest.projects.project.files.file

    foreach($file in $files.filename)
    {
        $results += $directoryNames + $file
    }
}

return $results

如果需要,您可以将其放入函数中以消除一些代码重复并创建可重用的脚本:

<#
.Synopsis
   Gets XML file to parse and displays results
.DESCRIPTION
   Reads content of an XML file, parses the
   manifest.projects.project.project_directory
   tag and displays concatenated results of 
   project.project_directory and child file.filename
   items
.EXAMPLE
   \Get-XMLFileItems -XMLFilePath "C:\users\myusername\desktop\myxmlfile.xml"
.EXAMPLE
   .\Get-XMLFileItems -XMLFilePath "C:\users\myusername\desktop\myxmlfile.xml" -MultipleDirectories $False
#>

[cmdletBinding()]
Param(
    [Parameter(Mandatory=$true)]
    [ValidateScript({Test-Path $_})]
    [string]$XMLFilePath,

    [Parameter()]
    [bool]$MultipleDirectories = $true
)

BEGIN
{
    Function Load-XMLFile
    {
        try
        {
            Write-Output "Loading XML file...`n"
            [xml]$XMLDocument = Get-Content $XMLFilePath

            Get-XMLDirectoryInfo -File $XMLDocument

        }
        catch [Exception]
        {
            Write-Error -Message "Error loading XML file $XMLFilePath"
        } 
    }

    Function Get-XMLDirectoryInfo($File)
    {
        try
        {
            $directoryCount = @($File.manifest.projects.project).Count
        }
        catch [Exception]
        {
            Write-Error "Unable to count 'manifest.projects.project' in schema"
        }  

        try
        {
            $directoryNames = $File.manifest.projects.project.project_directory
        }
        catch [Exception]
        {
            Write-Error "Unable to find names for items in 'manifest.projects.project.project_directory' in schema"
        }

        Get-FilesInXMLSchema -File $File
    }

    Function Get-FilesInXMLSchema($File)
    {
        for($i = 0 ; $i -lt $directoryCount; $i++)
        {
            if($MultipleDirectories -eq $true)
            {
                $files = $File.manifest.projects.project[$i].files.file

                foreach($item in $files.filename)
                {
                    [array]$results += $directoryNames[$i] + $item
                }
            }

            else
            {
                $files = $XmlDocument.manifest.projects.project.files.file

                foreach($item in $files.filename)
                {
                    [array]$results += $directoryNames + $item
                } 
            }
        }

        Show-Results -InputObject $results
    }

    Function Show-Results($InputObject)
    {
        try
        {
            return $InputObject
        }
        catch [Exception]
        {
            Write-Error -Message "Error displaying results"
        }
    }

    Function Write-Error($Message)
    {
        Write-Output $Message
        $Error[0]
        Write-Output "Exiting script"
        Exit
    }
}

PROCESS
{
    Load-XMLFile
}

END
{}

如果未指定-MultipleDirectories参数,则默认为$ true。检查开头的帮助注释以便使用。我针对您的XML示例测试了这个并且它可以工作。希望这有帮助!