Modifying XML with Powershell


i new modifying xml powershell please bare me.  ;-)

you may or may not notice xml file generate user driven installation wizard part of mdt 2012 toolkit.  (code block below)

in section in bold, need duplicate nodes dynamically based on array of values. 

example:  querying ad list  of "locations" tech select during udi wizard.  node combo box (denoted combo1 "data name") that need build prior launching udi wizard.  example of be:

<dataitem>
    <setter property="displayname">mo, st. louis | corporate | cdt</setter>
    <setter property="value">mo, st. louis | corporate | cdt</setter>
</dataitem>
<dataitem>
    <setter property="displayname">china, dongguan | china-dongguan | cht</setter>
    <setter property="value">china, dongguan | china-dongguan | cht</setter>
</dataitem>

i doing today using wisescript makes quite easy having keywords "replaceme" for, "insert after",  however trying move functionality powershell , struggling find example of managing these types of nodes.  lack of solid understanding of other basic xml.  :-/

i can read xml file , node shown below have tried thousand examples internet on how duplicate , re-write xml , have failed miserably.  hoping can jump start brain on how attack this.

$xml = [xml](gc 'c:\tmp\newcomputer.xml')
$xml | select-xml "//data" |
foreach {
 if ($_.node.name -eq 'combo1') {
            write-host $_
        }
}

<?xml version="1.0" encoding="utf-8"?>  <wizard>    <dlls>      <dll name="osdrefreshwizard.dll" />      <dll name="sharedpages.dll" />    </dlls>    <style>      <setter property="bannerfilename">udi_wizard_banner.bmp</setter>      <setter property="title">operating system deployment (osd) wizard</setter>    </style>  <pages>  <page name="buildyourownpageview" displayname="select location" type="microsoft.wizard.custompage">        <fields>          <field name="combo1" enabled="true" summary="location" varname="location">            <default>replaceme</default>          </field>          <field name="label2" enabled="true" summary="" varname="">            <default>destination location:</default>          </field>          <field name="label3" enabled="true" summary="" varname="">            <default>your selection here determines following information:</default>          </field>          <field name="label5" enabled="true" summary="" varname="">            <default>- organizational unit (ou) machine placed in.</default>          </field>          <field name="label6" enabled="true" summary="" varname="">            <default>- timezone apply operating system.</default>          </field>          <field name="label7" enabled="true" summary="" varname="">            <default>- language pack apply (if applicable).</default>          </field>          <field name="line8" enabled="true" summary="" varname=""></field>        </fields>        <data name="customfields">          <dataitem>            <setter property="controltype">combo</setter>            <setter property="id">1</setter>            <setter property="x">10.62</setter>            <setter property="y">26.09</setter>            <setter property="width">242</setter>            <setter property="height">13</setter>            <setter property="name">combo1</setter>          </dataitem>          <dataitem>            <setter property="controltype">label</setter>            <setter property="id">2</setter>            <setter property="x">9.7</setter>            <setter property="y">12.73</setter>            <setter property="width">64</setter>            <setter property="height">11</setter>            <setter property="name">label2</setter>            <setter property="label">destination location:</setter>          </dataitem>          <dataitem>            <setter property="controltype">label</setter>            <setter property="id">3</setter>            <setter property="x">9.57</setter>            <setter property="y">104.28</setter>            <setter property="width">168</setter>            <setter property="height">13</setter>            <setter property="name">label3</setter>            <setter property="label">your selection here determines following information:</setter>          </dataitem>          <dataitem>            <setter property="controltype">label</setter>            <setter property="id">5</setter>            <setter property="x">24.54</setter>            <setter property="y">115.79</setter>            <setter property="width">192</setter>            <setter property="height">10</setter>            <setter property="name">label5</setter>            <setter property="label">- organizational unit (ou) machine placed in.</setter>          </dataitem>          <dataitem>            <setter property="controltype">label</setter>            <setter property="id">6</setter>            <setter property="x">24.54</setter>            <setter property="y">126.1</setter>            <setter property="width">175</setter>            <setter property="height">10</setter>            <setter property="name">label6</setter>            <setter property="label">- timezone apply operating system.</setter>          </dataitem>          <dataitem>            <setter property="controltype">label</setter>            <setter property="id">7</setter>            <setter property="x">24.54</setter>            <setter property="y">135.81</setter>            <setter property="width">159</setter>            <setter property="height">11</setter>            <setter property="name">label7</setter>            <setter property="label">- language pack apply (if applicable).</setter>          </dataitem>          <dataitem>            <setter property="controltype">line</setter>            <setter property="id">8</setter>            <setter property="x">0</setter>            <setter property="y">92.13</setter>            <setter property="width">252</setter>            <setter property="height">1</setter>            <setter property="name">line8</setter>          </dataitem>        </data>        <data name="combo1">          <dataitem>            <setter property="displayname">replaceme</setter>            <setter property="value">replaceme</setter>          </dataitem>        </data>      </page>      <page name="selectdeploymenttype" displayname="selection deployment type" type="microsoft.wizard.custompage">        <fields>          <field name="label4" enabled="true" summary="" varname="">            <default>select deployment type</default>          </field>          <radiogroup name="group1" locked="false" enabled="true" summary="deployment type" varname="deploymenttype">            <default>radiobutton1</default>          </radiogroup>        </fields>      </page>    </pages>

there tones of different ways of achieving this. hardcore way of not using text strings using xml object model in .net, takes time though code , lazy. :)

so started off select-xml perfect if want use xpath. not comfortable xpath if ask me xpath awesome. show 2 ways. select-xml xpath way , powershell parsing of [xml] way.

[xml]$xml = @" <?xml version="1.0" encoding="utf-8"?> <wizard> ... </wizard> "@ $dataitem = @" <dataitem> <setter property="displayname">mo, st. louis | corporate | cdt</setter> <setter property="value">mo, st. louis | corporate | cdt</setter> </dataitem> <dataitem> <setter property="displayname">china, dongguan | china-dongguan | cht</setter> <setter property="value">china, dongguan | china-dongguan | cht</setter> </dataitem> "@ # xpath way

$datacombo1 = select-xml -xml $xml -xpath "//data[@name = 'combo1']" $datacombo1.node.innerxml = $dataitem # powershell way

$datacombo1node = $xml.wizard.pages.page | where-object name -eq 'buildyourownpageview' | select-object -expandproperty data | where-object name -eq "combo1" $datacombo1node.innerxml = $dataitem # save xml

$xml.save("c:\ps\file.xml")

in first example select node select-xml , xpath statement can read "select data nodes root xml attribute name equal combo1".

the resulting object has node property contains actual node. have other attributes here path , xpath pattern used well. go node , node has property called innerxml. inner xml expressed string. settable property , set $dataitem string containing xml snippet want inject.

in second method, powershell method, same node object , set innerxml use where-object , select-object navigate our way through xml nodes.

i hope helps you.


--neptune



Windows Server  >  Windows PowerShell



Comments

Popular posts from this blog

Error: 0x80073701 when trying to add Print Services Role in Windows 2012 Standard

Disconnecting from a Windows Server 2012 R2 file sharing session on a Windows 7,8,10 machine

Windows 2016 RDS event 1306 Connection Broker Client failed to redirect the user... Error: NULL