FAQ FAQ  Forum Search   Register Register  Login Login

editing xml

 Post Reply Post Reply
Author
  Topic Search Topic Search  Topic Options Topic Options
jonjames View Drop Down
I'm new here
I'm new here


Joined: 25 Jun 2008
Online Status: Offline
Posts: 26
  Quote jonjames Quote  Post ReplyReply bullet Topic: editing xml
    Posted: 04 Jul 2009 at 04:04
Hi
 
I've been using this script (Thanks jvierra): which adds and populates the bypass element
to a web.config file
 
$filename = "c:\web.config"
$xml= [xml] (Get-Content $filename)
$target=$xml.selectSingleNode("//system.net")
$newNode=$xml.createElement("bypasslist")
$target.defaultProxy.AppendChild($newNode)
$addnode = $xml.createElement("add")
$newNode.AppendChild($addNode)
$newAttribute = $xml.CreateAttribute("address")
$newAttribute.set_Value(https://test03.com)
$addNode.SetAttributeNode($newAttribute )
$xml.Save("$filename.xml")

and it works fine as long as the <bypasslist> element is not already present in the web.config - when it is I'm finding that it results in this:
 
   <defaultProxy>
      <proxy proxyaddress="http://172.16.12.118:8080" bypassonlocal="true" />
      <bypasslist>
        <add address="test.com" />
        <add address="test02.com" />
      </bypasslist>
      <bypasslist>
        <add address="http://test03.com" />
      </bypasslist>
    </defaultProxy>
 
 
--> i.e. it adds a second <bypasslist> element
 
My question is - how can make the script work so that if a <bypasslist> element exists in the web.config it populates it and if it doesn't exist is creates and populates it
 
It's probably somethjing along the lines of an If-Then-Else statement but I'm struggling to make it work and any help would really be appreciated
 
Cheers
 
jonj
Back to Top
jvierra View Drop Down
MVP
MVP


Joined: 31 Aug 2006
Location: United States
Online Status: Offline
Posts: 6846
  Quote jvierra Quote  Post ReplyReply bullet Posted: 04 Jul 2009 at 07:48
You need to use the same method but check to see if the node exisits.
 
$target=$xml.selectSingleNode("//bypasslist")
if (-not $target){
   # add node "bypasslist"
}
 
# add node "add" to $target
 
 
To edit XML in PoSH just isolate teh node you want either by direct reference or by XPath query then, using the referenced node just assign the value or add other attributes.
 
Remember that XML is case sensitive. Tag names that differ in case are different.  test and TEST are different tags.
 
Ideally tags should not contain punctuation and other marks even though Microsoft breaks this rule often.  However, since they own the schema they can get away with it.  PoSH XML can have issues with tags with punctuation in them like <system.net>
 
Be very careful with web.config.  It is very complex and can be very easily broken leading to some very difficult to solve problems.  Always keep all usable version of web.config until you are absolutely sure everything works correctly.  This is not as important for site specific config files but is absolute for the root web.config or teh machine web.config.
 
web.config is additive in the hierarchy unless a more local file overrides the hierarchy.
 
Edits to the web.config file cause the site or the web server to restart. In some cases the existing sessions will become invalid when the site is restarted.
 
Be sure that proxy settings for machine.config are not the ones you wish to set as web.config may not give you what you want.
 


Edited by jvierra - 04 Jul 2009 at 08:19
Back to Top
jonjames View Drop Down
I'm new here
I'm new here


Joined: 25 Jun 2008
Online Status: Offline
Posts: 26
  Quote jonjames Quote  Post ReplyReply bullet Posted: 04 Jul 2009 at 08:08
Thanks jvierra - still not entirely sure how to fit this into the existing script but at least I've got something to work with now
 
thank you
 
Cheers
 
Jonj
Back to Top
jvierra View Drop Down
MVP
MVP


Joined: 31 Aug 2006
Location: United States
Online Status: Offline
Posts: 6846
  Quote jvierra Quote  Post ReplyReply bullet Posted: 04 Jul 2009 at 08:22
Just in case here is the XPath to find a proxy address from the root.  You should use it to validate the existence of an address before adding it or just use the above method.  Dupe entries will always default to the last entry value so dupes don't matter for child nodes but may for group nodes.  If these nodes "add" had children then dupoes would matter as only the children of the last node would be used I believe. Of course some subsystems will aggregate like nodes which is how the sub hierarchy that MS has designed here probably works.
 
The following query select the "add" level and asks for teh attribute "address" whose value equals $proxy.  The single quotes are required.
 

$proxy = "https://test88.com"
$xml.selectNodes("/configuration/system.net/defaultProxy/bypasslist/add[@address='$proxy']")
 
 


Edited by jvierra - 04 Jul 2009 at 08:30
Back to Top
jvierra View Drop Down
MVP
MVP


Joined: 31 Aug 2006
Location: United States
Online Status: Offline
Posts: 6846
  Quote jvierra Quote  Post ReplyReply bullet Posted: 04 Jul 2009 at 09:06
Here is an approximation of what you are looking for.  Remember that this needs more testing before using it in production. You may also want to add more eror checking such as for file existence and legal address formats.
 
The following will work in a pipeline that is fed with an arry of strings so input of addresses from a file is possible.  It will also use single addresses as an argument.  It could be or should be turned into a PS1 script file but here it is as a function.
 

function Add-Proxy( [string]$filename, [string]$proxyaddress ){
    begin{
        $xml= [xml] (Get-Content $filename)
        $target=$xml.selectSingleNode("//bypasslist")
        if ( -not $target){
            $target=$xml.selectSingleNode("//system.net")
            $newNode=$xml.createElement("bypasslist")
            $target.defaultProxy.AppendChild($newNode)
            $target = $newNode
        }
    }
    process{
        if($_){$proxyaddress=$_}
        $a = $xml.selectSingleNode("/configuration/system.net/defaultProxy/bypasslist/add[@address='$proxyaddress']")
        if(-not $a){
            $addnode = $xml.createElement("add")
            $target.AppendChild($addNode)
            $newAttribute = $xml.CreateAttribute("address")
            $newAttribute.set_Value($proxyaddress)
            $addNode.SetAttributeNode($newAttribute )
            Write-Host "Proxy Address: $proxyaddress added" -fore green
        }else{
            Write-Host "Proxy Address: $proxyaddress Already in list" -fore blue
        }
    }
    end{
        $xml.Save($filename)
    }
}

#Example #1

 
#Example #2
cat addresses.txt | Add-Proxy "c:\web.config"
#Example #3
Add-Proxy "c:\web.config" "https:\\test4.com"
 
Back to Top
jvierra View Drop Down
MVP
MVP


Joined: 31 Aug 2006
Location: United States
Online Status: Offline
Posts: 6846
  Quote jvierra Quote  Post ReplyReply bullet Posted: 04 Jul 2009 at 09:27
Here are the missing utility functions that may be needed to maintain the proxy list.  One function saves the list to a file and the other empties the list in case it gets full of junk. The third function display the current contents of teh list.
 

function Save-Proxy( [string]$configfile, [string]$savefile ){
        $xml= [xml] (Get-Content $configfile)
        $nodes=$xml.selectNodes("/configuration/system.net/defaultProxy/bypasslist/add[@address]")
        $nodes|%{$_.address}|Out-File $savefile      
}
Save-Proxy "c:\web.config" "c:\addresses.txt"
function Delete-Proxy( [string]$configfile){
        $xml= [xml] (Get-Content $configfile)
        $nodes=$xml.selectNodes("/configuration/system.net/defaultProxy/bypasslist")
        $nodes | %{$_.RemoveAll()}
        $xml.Save($configfile)
}
Delete-Proxy "c:\web.config"
function List-Proxy( [string]$configfile){
        $xml= [xml] (Get-Content $configfile)
        $nodes=$xml.selectNodes("/configuration/system.net/defaultProxy/bypasslist/add[@address]")
        $nodes | select address
}
List-Proxy "c:\web.config"
 
 
I did the above because it tuens out to be a pretty good sampler of how to use PowerShell and the [xml] type to manage an XML file.  These functions are similar to any edit and management functions that might be needed for simple XML file maintenance.
 
 


Edited by jvierra - 04 Jul 2009 at 09:30
Back to Top
jonjames View Drop Down
I'm new here
I'm new here


Joined: 25 Jun 2008
Online Status: Offline
Posts: 26
  Quote jonjames Quote  Post ReplyReply bullet Posted: 06 Jul 2009 at 02:50
This is great stuff jvierra - really useful - thanks again -
 
Jonj
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down