A while back, Jeffrey posted an article on how to use string expansion and XML casts to build XML documents in-line in a PowerShell script:
http://blogs.msdn.com/powershell/archive/2007/05/29/using-powershell-to-generate-xml-documents.aspx
The overall feel of the approach that Jeffrey described is very much like that of ASP, JSP, PHP on any of the other systems that use “holes” to embed code to dynamically generate document content within the document itself. Ari over at the Windows Core Networking blog had some concerns about this approach for various reasons. You can see his comments at:
http://blogs.msdn.com/wndp/archive/2007/06/15/offtopic-another-way-to-generate-xml-in-powershell.aspx
As an alternative, he suggests a mixed approach that combines strings and the .NET XmlDocument APIs. The result looks like:
$doc = [xml] “
element = “ns:TestBuild”
attributes = @{
Lab = $lab
BuildNumber = $buildnumber
SPBuildNumber = $OSBuildNumber
TimeStamp = $BuildLabString.Split(“.”)[4]
SKU = $sku
Language = $SystemLocale.Split(“-“)[0].Trim()
Culture = $SystemLocale.Split(“-“)[1].Trim()
Architecture = $Processor
Type = $Type
}
}
@{
element = “ns:Implementation”
attributes = @{
type = “WTTResource”
ResourceName = $Name
ResourceId = $ResourceId
ResourceConfigurationId = $Id
}
}
}
$doc.save((Join-path $RolePath “RoleInstance.xml”))
What I’ve done here is create a script New-XmlDocument. This command takes a scriptblock as its only argument. The scriptblock contains a number of hash literals that describe the elements to create. Each hashtable contains two members – the type of element to build and the list of its attributes. The attribute list is, in turn, a hashtable with name/value pairs for each attribute. A similar approach could be used to add child notes at each level. The script to process this data structure turns out to be quite simple: param ([scriptblock] $sb)
# Hard coded for now – should be parameterized
$doc = [xml] ‘
# Execute the scriptblock to get the list of element hashtables
$elements = & $sb
# Now iterate over the list construction elements then adding
# the specified attributes.
foreach ($e in $elements)
{
$elem = $doc.CreateElement($e.element)
foreach ($attr in $e.Attributes.GetEnumerator())
{
$elem.SetAttribute($attr.name, $attr.value)
}
# The next step would be to recursively construct the
# children of this node but that’s not implemented yet…
# Finally add this element
[void] $doc.get_ChildNodes().Item(1).AppendChild($elem)
}
#
# Return the constructed document…
# $doc
While this script is not a complete solution (it doesn’t support building child nodes) it does illustrate how, in a few lines of code, you can build a custom “language” that lets you express the intent of your solution clearly and concisely. You can also take advantage of PowerShell’s use of dynamic scopes to specify “resources” in the document description by simply defining a variable at one level and then using it in a nested scope. You can create “base” attribute descriptions as hashtables stored in these resource variables and then derive complete descriptions by using PowerShell’s ability to add two hashtables together. Finally, instead of directly encoding all of the literal hashtables, you can could a function in the body of the document that returns a collection of hashtables simplifying the construction of repeated nodes. There is one other very useful extension that could be added to this script and that’s schema validation. As each element is constructed, it would be easy to check a hashtable to see if the element is permitted in the document. Once you have the element, additional hashtables can be used to verify that the attributes are correct and are of the correct type, etc. As you might imagine, the schema notation once again lends itself to a “little language” solution, however it is left as an exercise to the reader J -bruce =================================================================== Bruce Payette [MSFT]
Windows PowerShell Tech Lead
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
Windows PowerShell in Action (book): http://manning.com/powershell
XmlBuilder.zip
0 comments