XmlNode.SelectSingleNode 递归导出 CSV

XmlNode.SelectSingleNode recursively to export CSV

我正在尝试从 XML 配置中导出带有 FileZillaServer 数据的 csv。 它按预期工作,除了条件 Where-Object 因为它停止在同名的第一个块 <Permissions> 上。 只有当它设置为 HomeDirectory "IsHome">1

时,我才想获得 Permission Dir

XMl 包含:

<FileZillaServer>
    <Users>
        <User Name="USER1">
          <Option Name="Pass">e1923304e508b24dc0</Option>
          <Option Name="Salt"></Option>
          <Option Name="Group"></Option>
          <Option Name="Bypass server userlimit">1</Option>
          <Option Name="User Limit">0</Option>
          <Option Name="IP Limit">0</Option>
          <Option Name="Enabled">0</Option>
          <Option Name="Comments">Comment 1</Option>
          <Option Name="ForceSsl">0</Option>
          <IpFilter>
                <Disallowed />
                <Allowed />
          </IpFilter>
          <Permissions>
                <Permission Dir="C:\folder1\subfolder1">
                    <Option Name="FileRead">1</Option>
                    <Option Name="FileWrite">1</Option>
                    <Option Name="FileDelete">1</Option>
                    <Option Name="FileAppend">0</Option>
                    <Option Name="DirCreate">0</Option>
                    <Option Name="DirDelete">0</Option>
                    <Option Name="DirList">1</Option>
                    <Option Name="DirSubdirs">1</Option>
                    <Option Name="IsHome">0</Option>
                    <Option Name="AutoCreate">0</Option>
                </Permission>
                <Permission Dir="C:\folder1\subfolder2">
                    <Option Name="FileRead">1</Option>
                    <Option Name="FileWrite">0</Option>
                    <Option Name="FileDelete">0</Option>
                    <Option Name="FileAppend">0</Option>
                    <Option Name="DirCreate">0</Option>
                    <Option Name="DirDelete">0</Option>
                    <Option Name="DirList">1</Option>
                    <Option Name="DirSubdirs">1</Option>
                    <Option Name="IsHome">1</Option>
                    <Option Name="AutoCreate">0</Option>
                </Permission>
              </Permissions>
                    <SpeedLimits DlType="0" DlLimit="10" ServerDlLimitBypass="0" UlType="0" UlLimit="10" ServerUlLimitBypass="0">
                <Download />
                <Upload />
          </SpeedLimits>
        </User>
    </Users>
</FileZillaServer>

我正在使用此代码:

$xmlFilePath = "C:\FileZilla Server.xml"
$newcsv = "C:\newcsv.csv"
$xml = [xml](Get-Content $xmlFilePath)
 
$results = foreach ($user in $xml.FileZillaServer.Users.User){                                                
                [pscustomobject]@{
                User = $user.Name
                Comment = $Comments = $user.SelectSingleNode("Option[@Name='Comments']").InnerText = $user.SelectSingleNode("Option[@Name='Comments']").InnerText
                ForceSSl = $ForceSSL = $user.SelectSingleNode("Option[@Name='ForceSsl']").InnerText = $user.SelectSingleNode("Option[@Name='ForceSsl']").InnerTex
                Enabled = $Enabled = $user.SelectSingleNode("Option[@Name='Enabled']").InnerText = $user.SelectSingleNode("Option[@Name='Enabled']").InnerText                          
                HomeDir = $user.Permissions.SelectSingleNode("Permission[@Dir]").Dir | Where-Object {$user.Permissions.SelectSingleNode("Permission[@Dir]/Option[@Name='IsHome']").InnerText -eq 1} 
                                 }                                                          
} $results | export-csv $newcsv -NoTypeInformation

您可以执行以下操作:

$xmlFilePath = "C:\FileZilla Server.xml"
$xml = [xml](Get-Content $xmlFilePath)
 
$results = foreach ($user in $xml.FileZillaServer.Users.User){                                                
               [pscustomobject]@{                        
                    HomeDir = $user.Permissions.SelectSingleNode("Permission[@Dir][./Option[@Name = 'IsHome'] = '1']").Dir
               } 
}                                                          

XPath 谓词 [./Option[@Name = 'IsHome'] = '1'] 创建一个条件,其中当前节点 (Permission) 包含子节点 Option,其属性称为 NameName 的值必须为 IsHome 并且该 Option 节点的文本必须为 1.


HomeDir 属性 未按预期设置的原因是选择条件的排序方式。

$user.Permissions.SelectSingleNode("Permission[@Dir]").Dir 选择名为 Permission 的第一个节点,其中包含名为 Dir 的属性。选择该节点后,将在该 PowerShell 对象上引用 属性 Dir。最终,您将返回表示 Dir 的字符串,然后将其通过管道传输到 Where-Object。之后的任何管道 Where-Object 条件只会进一步过滤该字符串。

如果你想依赖Where-Object来过滤,你可以这样做:

($user.Permissions.SelectNodes("Permission[@Dir]") | where {
    $_.SelectSingleNode("Option[@Name = 'IsHome']").Innertext -eq 1}).Dir

注意 Dir 属性 值是如何检索的 节点、属性和文本条件之后被应用。使用 SelectNodes() 是因为我们需要将所有潜在节点发送到 Where-Object 以便它进一步过滤。