Hi,
inspired by recent blog entries I was trying to create an XML configuration file for a powershell script.
Goal:
store the last date&time the script was successfully run and other run-time related information.
solution idea:
<?xml version="1.0" encoding="utf-8"?>
<config>
<setting name="last_extract_date">1970-01-01 00:00:00</setting>
<setting name="new_extract_date">2000-01-01 00:00:00</setting>
<setting name="extract_dir">data</setting>
</config>
You should add the time information to the XML node as *attribute* and not as value. If you add them as value, the value will be represented by #text. If you add them as attribute, they will be accessible by attribute name.
I created a small script for you that creates an xml file and stores the current date both ways so you can see the differences:
# CREATING XML FILE:$xml = New-Object xml$xml.psbase.PreserveWhitespace = $false$pi = $xml.CreateProcessingInstruction('xml', 'version="1.0"')$RootNode = $xml.createElement('Information')$xml.appendChild($pi) | Out-Null$xml.appendChild($rootNode) | Out-Null$node = $xml.psbase.DocumentElement$newnode = $xml.CreateElement('ScriptStart')$newnode.psbase.InnerText = Get-Date$attribute = $xml.createAttribute('time') $newnode.setAttributeNode($attribute) | Out-Null $newnode.setAttribute('time', (Get-Date))$node.Appendchild($newnode) | Out-Null$xml.Save("c:\kurs1\xml1.xml")Invoke-Item c:\kurs1\xml1.xml
# LOADING NEW XML FILE:$xml2 = New-Object xml$xml2.load("c:\kurs1\xml1.xml")$xml2.Information.ScriptStart[datetime]$xml2.Information.ScriptStart.time
Thanks Tobias,
I was aware of the 'workaround' to use attributes instead of values.
My question was targeting XML implementations that depend on values.
In other words should I understand your answer as:
"There is no way to set/get an XML element value using PowerShell!"?
Clarification greatly appreciated
Sure you can, I guess I misunderstood your question. Simplest way: place '#text' into a variable and use this instead:
$xml = New-Object xml$xml.load("c:\kurs1\xml1.xml")
$prop = '#text'$xml.Information.ScriptStart| ForEach-Object { $_.$prop = "New Value" }
Greatly appreciate your help so I was able to achieve what I wanted!
$file = "c:\kurs1\xml1.xml"
$prop = "#text"
# CREATING XML FILE:
$xml = New-Object xml
$xml.psbase.PreserveWhitespace = $false
$pi = $xml.CreateProcessingInstruction('xml', 'version="1.0"')
$RootNode = $xml.createElement('Information')
$xml.appendChild($pi) | Out-Null
$xml.appendChild($rootNode) | Out-Null
$node = $xml.psbase.DocumentElement
$newnode = $xml.CreateElement('config')
$newnode.psbase.InnerText = "path"
$newnode.setAttribute('name', "n1")
$node.Appendchild($newnode) | Out-Null
$newnode.psbase.InnerText = Get-Date
$newnode.setAttribute('name', "n2")
#note: had to assign 'null', using an empty string an error was thrown at time of 'value' update "$_.$prop = [string]$S"
# assume this is related to "$xml.psbase.PreserveWhitespace = $false"
$newnode.psbase.InnerText = "null"
$newnode.setAttribute('name', "n3")
$xml.Save($file)
get-content $file
# LOADING NEW XML FILE:
$xml2 = New-Object xml
$xml2.load($file)
$xml2.Information.config
#$xml2.Information.config.$prop
#####
$xml.load($file)
# sleep in order to get a different time than above
Start-Sleep -Milliseconds 2000
$S = get-date -format "yyyy-MM-dd-HHmmss"
write-host $S
$prop = '#text'
#update 'n3'
$xml.Information.config | Where-object { $_.name -eq 'n3' } |ForEach-Object { $_.$prop = [string]$S }
sorry I forgot to include output of 'get-content $file'
1) <?xml version="1.0"?>
<Information>
<config name="n1">path</config>
<config name="n2">02/23/2011 17:06:04</config>
<config name="n3">null</config>
</Information>
perfect, glad I could help...!