【问题标题】:XmlNode.SelectSingleNode recursively to export CSVXmlNode.SelectSingleNode 递归导出 CSV
【发布时间】:2023-03-10 17:00:01
【问题描述】:

我正在尝试从 XML 配置中导出包含 FileZillaServer 数据的 csv。 它按预期工作,除了条件Where-Object,因为它在第一个同名的块上停止<Permissions>。 我想获得 Permission Dir 值,前提是它设置为 HomeDirectory "IsHome">1

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

【问题讨论】:

  • 这可能是一个剪切和粘贴错误,但您的 xml 无效 - 它缺少 &lt;/Permissions&gt;,可能就在 &lt;SpeedLimits DlType="0"... 之前。
  • 您能否还显示您的 xml 中预期的 csv 输出应该是什么?
  • 我认为第一个 SelectSingleNode() 总是希望选择第一个选项,因为您的条件语句存在于其 XPath 之外。也许HomeDir = ($user.Permissions.SelectNodes("Permission[@Dir]") | where {$_.SelectSingleNode("Option[@Name = 'IsHome']").Innertext -eq 1}).Dir 会有更好的结果。一旦您引用.Dir,节点选择就会结束,因为这是文本元素。因此,这应该最后发生。
  • 如果您愿意,您可以在 XPath 中完成所有操作 - FileZillaServer/Users/User/Permissions/Permission[descendant::Option[@Name='IsHome']='1'] - 即获取所有 Permission 节点,其中有一个名为 IsHome 和值 1 的子节点 Option .请参阅xpather.com/vhV0c4Zy 进行现场演示。

标签: xml powershell export-to-csv


【解决方案1】:

您可以执行以下操作:

$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,其属性名为 Name。 Name 的值必须为 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 以便进一步过滤。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-05
    相关资源
    最近更新 更多