A thing of beauty is a joy for ever
So - I've been using the Windows Powershell for the odd bit of Tridion work. You knew that.
And you probably also knew that very often the Tridion API hands you back a string representing an XML document, and that it's very convenient to "cast" this to a .NET XmlDocument using the [xml] operator. Just search on this blog for "powershell" and you'll find enough examples. But still - there's a missing piece in the puzzle. So today I wanted to look at the output from the .GetTridionWebSchemaXMl() method on a Tridion Object Model Schema object. (Don't worry - I am weaning myself off the TOM; I wanted to compare this API with the ReadSchemaFields() method on the core service client API.)
Anyway - for what it's worth, here's what the raw string looks like:
> $tdse.GetObject("tcm:21-509-8",1).GetTridionWebSchemaXML(1919,$true)<tcm:TridionWebSchema ID="tcm:21-509-8" IsEditable="false" xmlns:tcm="http://www.tridion.com/ContentManager/5.0"><tcm:Context xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:transform-ext="urn:tridion:transform-ext"><tcm:Publication xlink:type="simple" xlink:title="Synchroniser tests" xlink:href="tcm:0-21-1" /><tcm:OrganizationalItem xlink:type="simple" xlink:title="TestSchemaOne" xlink:href="tcm:21-50-2" /></tcm:Context><tcm:Info xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:transform-ext="urn:tridion:transform-ext"><tcm:LocationInfo><tcm:WebDAVURL>/webdav/Synchroniser%20tests/Building%20Blocks/TestSchemaOne/TestSchemaCategories.xsd</tcm:WebDAVURL><tcm:Path>\Synchroniser tests\Building Blocks\TestSchemaOne</tcm:Path></tcm:LocationInfo><tcm:BluePrintInfo><tcm:OwningPublication xlink:type="simple" xlink:title="Synchroniser tests" xlink:href="tcm:0-21-1" /><tcm:IsShared>false</tcm:IsShared><tcm:IsLocalized>false</tcm:IsLocalized></tcm:BluePrintInfo><tcm:VersionInfo><tcm:Version>3</tcm:Version><tcm:Revision>0</tcm:Revision><tcm:CreationDate>2012-07-07T18:28:23</tcm:CreationDate><tcm:RevisionDate>2012-07-09T20:18:21</tcm:RevisionDate><tcm:Creator xlink:type="simple" xlink:title="TRIDIONDEV\Administrator" xlink:href="tcm:0-11-65552" /><tcm:Revisor xlink:type="simple" xlink:title="TRIDIONDEV\Administrator" xlink:href="tcm:0-11-65552" /><tcm:ItemLock Title="No lock" Type="0" /><tcm:IsNew>false</tcm:IsNew></tcm:VersionInfo><tcm:AllowedActions><tcm:Actions Allow="1173513" Deny="102" Managed="0" /></tcm:AllowedActions></tcm:Info><tcm:Data xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:transform-ext="urn:tridion:transform-ext"><tcm:Title>TestSchemaCategories</tcm:Title><tcm:Description>TestSchemaCategories</tcm:Description><tcm:Purpose>Component</tcm:Purpose><tcm:NamespaceURI>uuid:f14d60ed-0f7c-4d1f-a2e3-97d1dfeb1a1f</tcm:NamespaceURI><tcm:RootElementName>Content</tcm:RootElementName><tcm:Fields><tcm:KeywordField><tcm:Name>ColoursOne</tcm:Name><tcm:Description>ColoursOne</tcm:Description><tcm:MinOccurs>1</tcm:MinOccurs><tcm:MaxOccurs>unbounded</tcm:MaxOccurs><tcm:Category xlink:type="simple" xlink:title="Colours" xlink:href="tcm:21-59-512" /><tcm:Size>1</tcm:Size><tcm:List Type="tree" /><tcm:ExtensionXml xmlns="http://www.sdltridion.com/ContentManager/R6" /></tcm:KeywordField><tcm:SingleLineTextField><tcm:Name>Animals</tcm:Name><tcm:Description>Test field with locally declared list</tcm:Description><tcm:MinOccurs>1</tcm:MinOccurs><tcm:MaxOccurs>1</tcm:MaxOccurs><tcm:Size>1</tcm:Size><tcm:List Type="select"><tcm:Entry>Horse</tcm:Entry><tcm:Entry>Haddock</tcm:Entry><tcm:Entry>Weasel</tcm:Entry></tcm:List><tcm:ExtensionXml xmlns="http://www.sdltridion.com/ContentManager/R6" /></tcm:SingleLineTextField></tcm:Fields><tcm:MetadataFields /><tcm:AllowedMultimediaTypes /><tcm:ComponentProcess xlink:type="simple" xlink:title="" xlink:href="tcm:0-0-0" /></tcm:Data></tcm:TridionWebSchema>
Yeah - erm ... Okaayyyy. Great.
OK - so how about we do the cast?
> [xml]$tdse.GetObject("tcm:21-509-8",1).GetTridionWebSchemaXML(1919,$true) TridionWebSchema ---------------- TridionWebSchema
Well - at least you can read it.. but seriously - also not super helpful if you just want to scan the XML with good-old-fashioned human eyeballs.
So what can we do? Well I got to the point where I actually typed the following into Google:
powershell pretty print xml
and the first hit was on Keith Hill's blog. Keith had written a nice little function that looks like this:
function XmlPrettyPrint([string]$xml) { $tr = new-object System.IO.StringReader($xml) $settings = new-object System.Xml.XmlReaderSettings $settings.CloseInput = $true $settings.IgnoreWhitespace = $true $reader = [System.Xml.XmlReader]::Create($tr, $settings) $sw = new-object System.IO.StringWriter $settings = new-object System.Xml.XmlWriterSettings $settings.CloseOutput = $true $settings.Indent = $true $writer = [System.Xml.XmlWriter]::Create($sw, $settings) while (!$reader.EOF) { $writer.WriteNode($reader, $false) } $writer.Flush() $result = $sw.ToString() $reader.Close() $writer.Close() $result }
A minute later, this function was in my Powershell profile (and I slightly altered the name and added an alias) so now I can do the following:
> ppx ([xml]$tdse.GetObject("tcm:21-509-8",1).GetTridionWebSchemaXML(1919,$true)).OuterXml <?xml version="1.0" encoding="utf-16"?> <tcm:TridionWebSchema ID="tcm:21-509-8" IsEditable="false" xmlns:tcm="http://www.tridion.com/ContentManager/5.0"> <tcm:Context xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:transform-ext="urn:tridion:transform-ext"> <tcm:Publication xlink:type="simple" xlink:title="Synchroniser tests" xlink:href="tcm:0-21-1" /> <tcm:OrganizationalItem xlink:type="simple" xlink:title="TestSchemaOne" xlink:href="tcm:21-50-2" /> </tcm:Context> <tcm:Info xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:transform-ext="urn:tridion:transform-ext"> <tcm:LocationInfo> <tcm:WebDAVURL>/webdav/Synchroniser%20tests/Building%20Blocks/TestSchemaOne/TestSchemaCategories.xsd</tcm:WebDAVURL> <tcm:Path>\Synchroniser tests\Building Blocks\TestSchemaOne</tcm:Path> </tcm:LocationInfo> <tcm:BluePrintInfo> <tcm:OwningPublication xlink:type="simple" xlink:title="Synchroniser tests" xlink:href="tcm:0-21-1" /> <tcm:IsShared>false</tcm:IsShared> <tcm:IsLocalized>false</tcm:IsLocalized> </tcm:BluePrintInfo> <tcm:VersionInfo> <tcm:Version>3</tcm:Version> <tcm:Revision>0</tcm:Revision> <tcm:CreationDate>2012-07-07T18:28:23</tcm:CreationDate> <tcm:RevisionDate>2012-07-09T20:18:21</tcm:RevisionDate> <tcm:Creator xlink:type="simple" xlink:title="TRIDIONDEV\Administrator" xlink:href="tcm:0-11-65552" /> <tcm:Revisor xlink:type="simple" xlink:title="TRIDIONDEV\Administrator" xlink:href="tcm:0-11-65552" /> <tcm:ItemLock Title="No lock" Type="0" /> <tcm:IsNew>false</tcm:IsNew> </tcm:VersionInfo> <tcm:AllowedActions> <tcm:Actions Allow="1173513" Deny="102" Managed="0" /> </tcm:AllowedActions> </tcm:Info> <tcm:Data xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:transform-ext="urn:tridion:transform-ext"> <tcm:Title>TestSchemaCategories</tcm:Title> <tcm:Description>TestSchemaCategories</tcm:Description> <tcm:Purpose>Component</tcm:Purpose> <tcm:NamespaceURI>uuid:f14d60ed-0f7c-4d1f-a2e3-97d1dfeb1a1f</tcm:NamespaceURI> <tcm:RootElementName>Content</tcm:RootElementName> <tcm:Fields> <tcm:KeywordField> <tcm:Name>ColoursOne</tcm:Name> <tcm:Description>ColoursOne</tcm:Description> <tcm:MinOccurs>1</tcm:MinOccurs> <tcm:MaxOccurs>unbounded</tcm:MaxOccurs> <tcm:Category xlink:type="simple" xlink:title="Colours" xlink:href="tcm:21-59-512" /> <tcm:Size>1</tcm:Size> <tcm:List Type="tree" /> <tcm:ExtensionXml xmlns="http://www.sdltridion.com/ContentManager/R6" /> </tcm:KeywordField> <tcm:SingleLineTextField> <tcm:Name>Animals</tcm:Name> <tcm:Description>Test field with locally declared list</tcm:Description> <tcm:MinOccurs>1</tcm:MinOccurs> <tcm:MaxOccurs>1</tcm:MaxOccurs> <tcm:Size>1</tcm:Size> <tcm:List Type="select"> <tcm:Entry>Horse</tcm:Entry> <tcm:Entry>Haddock</tcm:Entry> <tcm:Entry>Weasel</tcm:Entry> </tcm:List> <tcm:ExtensionXml xmlns="http://www.sdltridion.com/ContentManager/R6" /> </tcm:SingleLineTextField> </tcm:Fields> <tcm:MetadataFields /> <tcm:AllowedMultimediaTypes /> <tcm:ComponentProcess xlink:type="simple" xlink:title="" xlink:href="tcm:0-0-0" /> </tcm:Data> </tcm:TridionWebSchema>
So what's my point? Well I have a couple:
- The Internet is great (by which I mean, the people of the Internet are great.). I could have written that function myself in about half an hour. But in practice I might not have had the energy to do so at 10pm on a working Monday. Thanks to Keith's willingness to share, I had my solution inside a minute - working and tested. How cool is that?
- Somehow, this has just taken a little bit of the friction out of my working day, not to mention my so-called free time. I can now pull data straight out of a method that returns string, and get human-readable XML. This stuff makes a difference.
Thanks Keith - and all the other Keith's out there.
P.S. Maybe even nicely formatted XML will never be a thing of beauty, so apologies to Keats.