代码之家  ›  专栏  ›  技术社区  ›  surge3333

使用PowerShell构建XML

  •  1
  • surge3333  · 技术社区  · 5 月前

    我继承了这个用用户及其角色构建xml的脚本。它无法处理一个用户可以拥有多个角色的情况。

    以下是脚本摘录:

    $somePATH = "C:\wherever"
    "Dummy Header" | Set-Content $somePATH
    
    
    $data = @(
       [pscustomobject]@{Type='P';ID='Fred';Role='Operator';Domain='Home'}
       [pscustomobject]@{Type='P';ID='Fred';Role='Admin';Domain='Home'}
       [pscustomobject]@{Type='P';ID='Wilma';Role='Operator';Domain='Home'}
       [pscustomobject]@{Type='P';ID='Barney';Role='Admin';Domain='Work'}
       [pscustomobject]@{Type='N';ID='Betty';Role='Whatev';Domain='Home'}
    )
    
    Function BuildXML
    {
    param($Type, $ID, $Role, $Domain)
    $CC = "1234"
    $Account = "SNOW_CC$CC" + "_BNK0000_BLAH"
    
    if ($Type -eq "N") {
    
    @”
           <account id="$Account">
           <name><![CDATA[$ID@$Domain]]></name>
               <endPoint>UNC</endPoint>
               <domain>UNC</domain>
               <comments/>
               <attributes>
                   <attribute name="appUserName">
                       <attributeValues>
                           <attributeValue><value><![CDATA[$ID]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="CostCentre">
                       <attributeValues>
                           <attributeValue><value><![CDATA[$CC]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="Bank_Number">
                       <attributeValues>
                           <attributeValue><value><![CDATA[0000]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="Directory">
                       <attributeValues>
                           <attributeValue><value><![CDATA[BLAH]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="Role">
                       <attributeValues><attributeValueRef id="Role=$Role"/></attributeValues>
                   </attribute>
               </attributes>
           </account>
    "@ | Add-Content $somePATH
    
    
       } elseif ($Type -eq "P") {   
    
    @"
           <account id="$ID">
               <name><![CDATA[$ID@$Domain]]></name>
               <endPoint>ABC</endPoint>
               <domain>ABC</domain>
               <comments/>
               <attributes>
                   <attribute name="AppBoRID">
                       <attributeValues>
                           <attributeValue><value><![CDATA[$ID]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="Role">
                       <attributeValues><attributeValueRef id="Role=$Role"/></attributeValues>
                   </attribute>
               </attributes>
           </account>
    "@ | Add-Content $WORKPATH$FEEDFILENAME
       
       }
    } # End Function
    
    
    foreach ($d in $data) {BuildXML $d.Type $d.ID $d.Role $d.Domain}
    
    

    仅显示“Fred”用户的结果:

            <account id="Fred">
                <name><![CDATA[Fred@Home]]></name>
                <endPoint>ABC</endPoint>
                <domain>ABC</domain>
                <comments/>
                <attributes>
                    <attribute name="AppBoRID">
                        <attributeValues>
                            <attributeValue><value><![CDATA[Fred]]></value></attributeValue>
                        </attributeValues>
                    </attribute>
                    <attribute name="Role">
                        <attributeValues><attributeValueRef id="Role=Operator"/></attributeValues>
                    </attribute>
                </attributes>
            </account>
            <account id="Fred">
                <name><![CDATA[Fred@Home]]></name>
                <endPoint>ABC</endPoint>
                <domain>ABC</domain>
                <comments/>
                <attributes>
                    <attribute name="AppBoRID">
                        <attributeValues>
                            <attributeValue><value><![CDATA[Fred]]></value></attributeValue>
                        </attributeValues>
                    </attribute>
                    <attribute name="Role">
                        <attributeValues><attributeValueRef id="Role=Admin"/></attributeValues>
                    </attribute>
                </attributes>
            </account>
    

    我追求的是这样的东西,“弗雷德”只有一个条目,但它反映了两个“角色”:

           <account id="Fred">
                <name><![CDATA[Fred@Home]]></name>
                <endPoint>ABC</endPoint>
                <domain>ABC</domain>
                <comments/>
                <attributes>
                    <attribute name="AppBoRID">
                        <attributeValues>
                            <attributeValue><value><![CDATA[Fred]]></value></attributeValue>
                        </attributeValues>
                    </attribute>
                    <attribute name="Role">
                        <attributeValues><attributeValueRef id="Role=Operator"/></attributeValues>
                        <attributeValues><attributeValueRef id="Role=Admin"/></attributeValues>
                    </attribute>
                </attributes>
            </account>
    

    我不知道如何在单个用户条目中反映多个角色。

    感谢任何帮助。

    2 回复  |  直到 5 月前
        1
  •  1
  •   mklement0    5 月前
    • 巩固 [pscustomobject] 您的实例 $data 通过组合具有相同值的所有实例来创建数组 .ID 房地产价值转化为a 单一的 实例谁 .Role 属性是所有角色的聚合,您可以通过 Group-Object cmdlet。

    • 在每个合并实例上操作,使用 $(...) ,the subexpression operator 将代码嵌入到可扩展的here字符串中,该字符串迭代潜在的多个角色,并为每个角色创建一个XML元素。

    以下将所有内容放在一起;请注意,出于演示目的 BuildXml 函数将生成的XML输出到 显示 默认情况下:

    # Note the renaming of $Role to $Roles.
    # Look for the $($Roles.ForEach({...})) lines below.
    Function BuildXML {
      param($Type, $ID, $Roles, $Domain)
      $CC = '1234'
      $Account = "SNOW_CC$CC" + '_BNK0000_BLAH'
    
      if ($Type -eq 'N') {
    
        @”
           <account id="$Account">
           <name><![CDATA[$ID@$Domain]]></name>
               <endPoint>UNC</endPoint>
               <domain>UNC</domain>
               <comments/>
               <attributes>
                   <attribute name="appUserName">
                       <attributeValues>
                           <attributeValue><value><![CDATA[$ID]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="CostCentre">
                       <attributeValues>
                           <attributeValue><value><![CDATA[$CC]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="Bank_Number">
                       <attributeValues>
                           <attributeValue><value><![CDATA[0000]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="Directory">
                       <attributeValues>
                           <attributeValue><value><![CDATA[BLAH]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="Role">
    $($Roles.ForEach({
    "                   <attributeValues><attributeValueRef id=`"Role=$_`"/></attributeValues>"
    }) -join [Environment]::NewLine)
                   </attribute>
               </attributes>
           </account>
    "@ # | Add-Content $somePATH
    
    
      }
      elseif ($Type -eq 'P') {   
    
        @"
           <account id="$ID">
               <name><![CDATA[$ID@$Domain]]></name>
               <endPoint>ABC</endPoint>
               <domain>ABC</domain>
               <comments/>
               <attributes>
                   <attribute name="AppBoRID">
                       <attributeValues>
                           <attributeValue><value><![CDATA[$ID]]></value></attributeValue>
                       </attributeValues>
                   </attribute>
                   <attribute name="Role">
    $($Roles.ForEach({
    "                   <attributeValues><attributeValueRef id=`"Role=$_`"/></attributeValues>"
    }) -join [Environment]::NewLine)
                   </attribute>
               </attributes>
           </account>
    )               </attribute>
               </attributes>
           </account>
    "@ # | Add-Content $WORKPATH$FEEDFILENAME
       
      }
    } # End Function
    
    #"# Your original sample data.
    $data = @(
      [pscustomobject]@{Type = 'P'; ID = 'Fred'; Role = 'Operator'; Domain = 'Home' }
      [pscustomobject]@{Type = 'P'; ID = 'Fred'; Role = 'Admin'; Domain = 'Home' }
      [pscustomobject]@{Type = 'P'; ID = 'Wilma'; Role = 'Operator'; Domain = 'Home' }
      [pscustomobject]@{Type = 'P'; ID = 'Barney'; Role = 'Admin'; Domain = 'Work' }
      [pscustomobject]@{Type = 'N'; ID = 'Betty'; Role = 'Whatev'; Domain = 'Home' }
    )
    
    # Consolidate all instances that have the same .ID value into
    # a single instance each that collects all .Role values, using
    # Group-Object.
    $consolidatedData = 
      $data | Group-Object Id | ForEach-Object {
        if ($_.Count -gt 1) {
          # Use *member-access enumeration* to collect the .Role property values
          # from all members of the group.
          $_.Group[0].Role = $_.Group.Role
        }
        $_.Group[0]
      }
    
    # Build the XML for each potentially consolidated object.
    foreach ($d in $consolidatedData) { BuildXML $d.Type $d.ID $d.Role $d.Domain }
    
        2
  •  0
  •   Theo    5 月前

    为什么不追求这样的结果呢?

    <attribute name="Role">
        <attributeValues>
            <attributeValueRef>"Operator"</attributeValueRef>
            <attributeValueRef>"Admin"</attributeValueRef>
        </attributeValues>
    </attribute>
    

    无论如何,由于您正在使用Here String模板构建xml,我建议:

    通过为添加单个值或值数组来更改数据 Role 房地产类

    $data = @(
        [pscustomobject]@{Type='P';ID='Fred';Role='Operator', 'Admin';Domain='Home'}
        ...
    )
    

    然后重写函数

    function BuildXML {
        param(
            [char]$Type,
            [string]$ID,
            [string[]]$Role,   # string array or single value
            [string]$Domain
        )
        $CC = "1234"
        $Account = "SNOW_CC$CC" + "_BNK0000_BLAH"
    
    # Change the templates by adding a placeholder text you can replace later
    $typeN = @"
        <account id="$Account">
            <name><![CDATA[$ID@$Domain]]></name>
            <endPoint>UNC</endPoint>
            <domain>UNC</domain>
            <comments/>
            <attributes>
                <attribute name="appUserName">
                    <attributeValues>
                        <attributeValue><value><![CDATA[$ID]]></value></attributeValue>
                    </attributeValues>
                </attribute>
                <attribute name="CostCentre">
                    <attributeValues>
                        <attributeValue><value><![CDATA[$CC]]></value></attributeValue>
                    </attributeValues>
                </attribute>
                <attribute name="Bank_Number">
                    <attributeValues>
                        <attributeValue><value><![CDATA[0000]]></value></attributeValue>
                    </attributeValues>
                </attribute>
                <attribute name="Directory">
                    <attributeValues>
                        <attributeValue><value><![CDATA[BLAH]]></value></attributeValue>
                    </attributeValues>
                </attribute>
                <attribute name="Role">
                    <attributeValues>
    @@ROLES@@
                    </attributeValues>
                </attribute>
            </attributes>
        </account>
    "@
    
    $typeP = @"
        <account id="$ID">
            <name><![CDATA[$ID@$Domain]]></name>
            <endPoint>ABC</endPoint>
            <domain>ABC</domain>
            <comments/>
            <attributes>
                <attribute name="AppBoRID">
                    <attributeValues>
                        <attributeValue><value><![CDATA[$ID]]></value></attributeValue>
                    </attributeValues>
                </attribute>
                <attribute name="Role">
                    <attributeValues>
    @@ROLES@@
                    </attributeValues>
                </attribute>
            </attributes>
        </account>
    "@
    
        if ($Type -eq "N") { $xmlTemplate = $typeN }
        else { $xmlTemplate = $typeP }
    
        # Replace the @@ROLES@@ placeholder
        # adjust this spacer to the number of tabs in your actual xml do it looks nice
        $spacer = "`t" * 5   # 5 TABS in this example
        $roleAttribs = $(foreach ($userRole in $Role) {
            '{0}<attributeValueRef id="Role={1}"/>' -f $spacer, $userRole
        }) -join [environment]::NewLine
        # save to file
        $xmlTemplate -replace '@@ROLES@@', $roleAttribs | Add-Content $WORKPATH$FEEDFILENAME
    }
    
    # for demo:
    BuildXML -Type 'P' -ID 'Fred' -Role 'Admin', 'Operator' -Domain 'whatever.com'
    

    结果将是

        <account id="Fred">
            <name><![CDATA[[email protected]]]></name>
            <endPoint>ABC</endPoint>
            <domain>ABC</domain>
            <comments/>
            <attributes>
                <attribute name="AppBoRID">
                    <attributeValues>
                        <attributeValue><value><![CDATA[Fred]]></value></attributeValue>
                    </attributeValues>
                </attribute>
                <attribute name="Role">
                    <attributeValues>
                        <attributeValueRef id="Role=Admin"/>
                        <attributeValueRef id="Role=Operator"/>
                    </attributeValues>
                </attribute>
            </attributes>
        </account>
    

    我还建议您将函数重命名为以下内容 Approved Verbs .
    也许 Format-UserXml 会是个主意吗?