c# - Parsing Mac XML PList into something readable -


i trying pull data xml plist (apple system profiler) files, , read memory database, , want turn human-readable.

the problem format seems difficult read in consistent manner. have gone on few solutions already, haven't found solution yet found satisfying. end having hard code lot of values, , end having many if-else/switch statements.

the format looks this.

<plist>     <key>_system</key>     <array>      <dict>       <key>_cpu_type</key>       <string>intel core duo</string>      </dict>     </array> </plist> 

example file here.

after have read (or during reading), make use of internal dictionary use determine type of information is. example, if key cpu_type save information accordingly.


a few examples have tried (simplified) pull information.

 xmltextreader reader = new  xmltextreader("c:\\test.spx");   reader.xmlresolver = null;   reader.readstartelement("plist");   string key = string.empty; string str  = string.empty;   int32 index = 0;   while (reader.read()) {       if (reader.localname == "key")      {          index++;          key = reader.readstring();      }      else if (reader.localname == "string")      {          str = reader.readstring();           if (key != string.empty)          {              dct.add(index, new keypair(key, str));              key = string.empty;          }      }  } 

or this.

foreach (var d in xdoc.root.elements("plist"))    dict.add(d.element("key").value,> d.element("string").value); 

i found framework, may able modify here.


some more useful information

mac os x information on system profiler here.

apple script used parse xml-files here.


any advise or insight appreciated.

my first thought use xslt (xsl transformations). don't know format looking based on answer in above comments, think got gist @ least. unless there's special need didn't think of, believe xslt powerful enough need, , no need bunch of complicated looping constructs.

if you're not familiar, there's lot of information on xslt on w3schools (probably start @ intro: http://www.w3schools.com/xsl/xsl_intro.asp) , wikipedia has decent writeup on (http://en.wikipedia.org/wiki/xslt).

it takes me while rules working way want; it's different way of thinking kind of transform , took me getting used to. it's necessary have decent understanding of xpath well. having refer both xslt spec (http://www.w3.org/tr/xslt) , xpath spec (http://www.w3.org/tr/xpath/) since i've had small amount of experience it, once have worked while goes more smoothly.

anyway, have app wrote playing around these translations. it's c# application 3 textboxes: 1 xslt, 1 source, , 1 output. spent few (okay, many) hours trying first cut of xslt process sample data, idea of how hard , structure of transform be. think figured out pretty needed, since don't know format need, stopped there.

here's link sample transformed output: http://pastebin.com/smfxuddk.

following code transform, included in form can use develop go. it's not fancy has worked me. "heavy lifting" done in "btntransform_click()" handler, plus have implemented xmlstringwriter make easy output things way want. main bit of work here in coming xslt directives, actual transform handled in .net xslcompiledtransform class. however, figured had spent enough time figuring out little details on when wrote it worth giving working example...

be aware changed couple of occurrences of namespace here on-the-fly, , added light comments xslt, if there issues let me know , correct them.

so, no further adieu: ;)

the xslt file:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet                         version="1.0"                         xmlns:xsl="http://www.w3.org/1999/xsl/transform"                         xmlns:msxsl="urn:schemas-microsoft-com:xslt"                         exclude-result-prefixes="msxsl"                         xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"                         xmlns:xsd="http://www.w3.org/2001/xmlschema"                         xmlns:fn="http://www.w3.org/2005/xpath-functions" >   <!-- says output xml opposed html or raw text -->   <xsl:output method="xml" indent="yes" xsi:type="xsl:output" />    <!-- matches root element , creates root element -->   <!-- more templates applied children -->   <xsl:template match="/" priority="9" >     <xsl:element name="root" xmlns="http://www.tempuri.org/plist">       <xsl:apply-templates/>     </xsl:element>   </xsl:template>    <!-- wasn't sure how want dict , arrays handled -->   <!-- final cut, make them parent nodes of -->   <!-- data underneath them, , apply templates -->    <xsl:template match="dict" priority="3" >     <xsl:element name="dictionary" xmlns="http://www.tempuri.org/plist">       <xsl:apply-templates/>     </xsl:element>   </xsl:template>    <xsl:template match="array" priority="5" >     <xsl:element name="list" xmlns="http://www.tempuri.org/plist">       <xsl:apply-templates/>     </xsl:element>   </xsl:template>    <!-- actually, figuring following step out hung me up; -->   <!-- issue here i'm taking text out of string/integer/date -->   <!-- nodes , putting them elements named after 'key' nodes -->    <!-- because of this, have have template match -->   <!-- nodes consuming , using conditional -->   <!-- process 'key' nodes.  also, there couple of -->   <!-- stray characters in source xml; think encoding -->   <!-- issue, stripped them out "translate" call when -->   <!-- creating keyname variable. since 2 -->   <!-- , because looked strays, did not worry -->   <!-- further.  reason issue because -->   <!-- creating elements out of contents of keys, , key names -->   <!-- restricted in characters can use. -->    <xsl:template match="key|string|integer|date" priority="1" >     <xsl:if test="local-name(self::node())='key'">       <xsl:variable name="keyname" select="translate(child::text(),' €™','---')" />       <xsl:element name="{$keyname}" xmlns="http://www.tempuri.org/plist" >         <!-- removed on-the-fly; had put in while testing           <xsl:if test="local-name(following-sibling::node())='string'">         -->           <xsl:value-of select="following-sibling::node()" />         <!--           </xsl:if>         -->       </xsl:element>     </xsl:if>   </xsl:template> </xsl:stylesheet> 

a little helper class made (xmlstringwriter.cs) :

using system; using system.collections.generic; using system.linq; using system.text;  using system.xml;  namespace xslttest.xml {     public class xmlstringwriter :         xmlwriter     {         public static xmlstringwriter create(xmlwritersettings settings)         {             return new xmlstringwriter(settings);         }          public static xmlstringwriter create()         {             return xmlstringwriter.create(xmlstringwriter.xmlwritersettings_display);         }          public static xmlwritersettings xmlwritersettings_display         {                         {                 xmlwritersettings xws = new xmlwritersettings();                 xws.omitxmldeclaration = false; // make choice?                 xws.newlinehandling = newlinehandling.replace;                 xws.newlineonattributes = false;                 xws.indent = true;                 xws.indentchars = "\t";                 xws.newlinechars = environment.newline;                 //xws.conformancelevel = conformancelevel.fragment;                 xws.closeoutput = false;                  return xws;             }         }          public override string tostring()         {             return myxmlstringbuilder.tostring();         }          //public static implicit operator xmlwriter(xmlstringwriter me)         //{         //   return me.myxmlwriter;         //}          //--------------          protected stringbuilder myxmlstringbuilder = null;         protected xmlwriter myxmlwriter = null;          protected xmlstringwriter(xmlwritersettings settings)         {             myxmlstringbuilder = new stringbuilder();             myxmlwriter = xmlwriter.create(myxmlstringbuilder, settings);         }          public override void close()         {             myxmlwriter.close();         }          public override void flush()         {             myxmlwriter.flush();         }          public override string lookupprefix(string ns)         {             return myxmlwriter.lookupprefix(ns);         }          public override void writebase64(byte[] buffer, int index, int count)         {             myxmlwriter.writebase64(buffer, index, count);         }          public override void writecdata(string text)         {             myxmlwriter.writecdata(text);         }          public override void writecharentity(char ch)         {             myxmlwriter.writecharentity(ch);         }          public override void writechars(char[] buffer, int index, int count)         {             myxmlwriter.writechars(buffer, index, count);         }          public override void writecomment(string text)         {             myxmlwriter.writecomment(text);         }          public override void writedoctype(string name, string pubid, string sysid, string subset)         {             myxmlwriter.writedoctype(name, pubid, sysid, subset);         }          public override void writeendattribute()         {             myxmlwriter.writeendattribute();         }          public override void writeenddocument()         {             myxmlwriter.writeenddocument();         }          public override void writeendelement()         {             myxmlwriter.writeendelement();         }          public override void writeentityref(string name)         {             myxmlwriter.writeentityref(name);         }          public override void writefullendelement()         {             myxmlwriter.writefullendelement();         }          public override void writeprocessinginstruction(string name, string text)         {             myxmlwriter.writeprocessinginstruction(name, text);         }          public override void writeraw(string data)         {             myxmlwriter.writeraw(data);         }          public override void writeraw(char[] buffer, int index, int count)         {             myxmlwriter.writeraw(buffer, index, count);         }          public override void writestartattribute(string prefix, string localname, string ns)         {             myxmlwriter.writestartattribute(prefix, localname, ns);         }          public override void writestartdocument(bool standalone)         {             myxmlwriter.writestartdocument(standalone);         }          public override void writestartdocument()         {             myxmlwriter.writestartdocument();         }          public override void writestartelement(string prefix, string localname, string ns)         {             myxmlwriter.writestartelement(prefix, localname, ns);         }          public override writestate writestate         {                          {                 return myxmlwriter.writestate;             }         }          public override void writestring(string text)         {             myxmlwriter.writestring(text);         }          public override void writesurrogatecharentity(char lowchar, char highchar)         {             myxmlwriter.writesurrogatecharentity(lowchar, highchar);         }          public override void writewhitespace(string ws)         {             myxmlwriter.writewhitespace(ws);         }     } } 

the windows forms designer class (frmxslttest.designer.cs)

namespace xslttest {     partial class frmxslttest     {         /// <summary>         /// required designer variable.         /// </summary>         private system.componentmodel.icontainer components = null;          /// <summary>         /// clean resources being used.         /// </summary>         /// <param name="disposing">true if managed resources should disposed; otherwise, false.</param>         protected override void dispose(bool disposing)         {             if (disposing && (components != null))             {                 components.dispose();             }             base.dispose(disposing);         }          #region windows form designer generated code          /// <summary>         /// required method designer support - not modify         /// contents of method code editor.         /// </summary>         private void initializecomponent()         {             this.splitcontainer1 = new system.windows.forms.splitcontainer();             this.btntransform = new system.windows.forms.button();             this.groupbox1 = new system.windows.forms.groupbox();             this.txtstylesheet = new system.windows.forms.textbox();             this.splitcontainer2 = new system.windows.forms.splitcontainer();             this.groupbox2 = new system.windows.forms.groupbox();             this.txtinputxml = new system.windows.forms.textbox();             this.groupbox3 = new system.windows.forms.groupbox();             this.txtoutputxml = new system.windows.forms.textbox();             ((system.componentmodel.isupportinitialize)(this.splitcontainer1)).begininit();             this.splitcontainer1.panel1.suspendlayout();             this.splitcontainer1.panel2.suspendlayout();             this.splitcontainer1.suspendlayout();             this.groupbox1.suspendlayout();             ((system.componentmodel.isupportinitialize)(this.splitcontainer2)).begininit();             this.splitcontainer2.panel1.suspendlayout();             this.splitcontainer2.panel2.suspendlayout();             this.splitcontainer2.suspendlayout();             this.groupbox2.suspendlayout();             this.groupbox3.suspendlayout();             this.suspendlayout();             //              // splitcontainer1             //              this.splitcontainer1.dock = system.windows.forms.dockstyle.fill;             this.splitcontainer1.location = new system.drawing.point(0, 0);             this.splitcontainer1.name = "splitcontainer1";             this.splitcontainer1.orientation = system.windows.forms.orientation.horizontal;             //              // splitcontainer1.panel1             //              this.splitcontainer1.panel1.controls.add(this.btntransform);             this.splitcontainer1.panel1.controls.add(this.groupbox1);             //              // splitcontainer1.panel2             //              this.splitcontainer1.panel2.controls.add(this.splitcontainer2);             this.splitcontainer1.size = new system.drawing.size(788, 363);             this.splitcontainer1.splitterdistance = 194;             this.splitcontainer1.tabindex = 0;             //              // btntransform             //              this.btntransform.anchor = ((system.windows.forms.anchorstyles)((system.windows.forms.anchorstyles.bottom | system.windows.forms.anchorstyles.left)));             this.btntransform.location = new system.drawing.point(6, 167);             this.btntransform.name = "btntransform";             this.btntransform.size = new system.drawing.size(75, 23);             this.btntransform.tabindex = 1;             this.btntransform.text = "transform";             this.btntransform.usevisualstylebackcolor = true;             this.btntransform.click += new system.eventhandler(this.btntransform_click);             //              // groupbox1             //              this.groupbox1.anchor = ((system.windows.forms.anchorstyles)((((system.windows.forms.anchorstyles.top | system.windows.forms.anchorstyles.bottom)              | system.windows.forms.anchorstyles.left)              | system.windows.forms.anchorstyles.right)));             this.groupbox1.controls.add(this.txtstylesheet);             this.groupbox1.location = new system.drawing.point(3, 3);             this.groupbox1.name = "groupbox1";             this.groupbox1.size = new system.drawing.size(782, 161);             this.groupbox1.tabindex = 0;             this.groupbox1.tabstop = false;             this.groupbox1.text = "stylesheet";             //              // txtstylesheet             //              this.txtstylesheet.dock = system.windows.forms.dockstyle.fill;             this.txtstylesheet.font = new system.drawing.font("lucida console", 7f, system.drawing.fontstyle.regular, system.drawing.graphicsunit.point, ((byte)(0)));             this.txtstylesheet.location = new system.drawing.point(3, 16);             this.txtstylesheet.maxlength = 1000000;             this.txtstylesheet.multiline = true;             this.txtstylesheet.name = "txtstylesheet";             this.txtstylesheet.scrollbars = system.windows.forms.scrollbars.both;             this.txtstylesheet.size = new system.drawing.size(776, 142);             this.txtstylesheet.tabindex = 0;             //              // splitcontainer2             //              this.splitcontainer2.dock = system.windows.forms.dockstyle.fill;             this.splitcontainer2.location = new system.drawing.point(0, 0);             this.splitcontainer2.name = "splitcontainer2";             //              // splitcontainer2.panel1             //              this.splitcontainer2.panel1.controls.add(this.groupbox2);             //              // splitcontainer2.panel2             //              this.splitcontainer2.panel2.controls.add(this.groupbox3);             this.splitcontainer2.size = new system.drawing.size(788, 165);             this.splitcontainer2.splitterdistance = 395;             this.splitcontainer2.tabindex = 0;             //              // groupbox2             //              this.groupbox2.controls.add(this.txtinputxml);             this.groupbox2.dock = system.windows.forms.dockstyle.fill;             this.groupbox2.location = new system.drawing.point(0, 0);             this.groupbox2.name = "groupbox2";             this.groupbox2.size = new system.drawing.size(395, 165);             this.groupbox2.tabindex = 1;             this.groupbox2.tabstop = false;             this.groupbox2.text = "input xml";             //              // txtinputxml             //              this.txtinputxml.dock = system.windows.forms.dockstyle.fill;             this.txtinputxml.font = new system.drawing.font("lucida console", 7f, system.drawing.fontstyle.regular, system.drawing.graphicsunit.point, ((byte)(0)));             this.txtinputxml.location = new system.drawing.point(3, 16);             this.txtinputxml.maxlength = 1000000;             this.txtinputxml.multiline = true;             this.txtinputxml.name = "txtinputxml";             this.txtinputxml.scrollbars = system.windows.forms.scrollbars.both;             this.txtinputxml.size = new system.drawing.size(389, 146);             this.txtinputxml.tabindex = 1;             //              // groupbox3             //              this.groupbox3.controls.add(this.txtoutputxml);             this.groupbox3.dock = system.windows.forms.dockstyle.fill;             this.groupbox3.location = new system.drawing.point(0, 0);             this.groupbox3.name = "groupbox3";             this.groupbox3.size = new system.drawing.size(389, 165);             this.groupbox3.tabindex = 1;             this.groupbox3.tabstop = false;             this.groupbox3.text = "output xml";             //              // txtoutputxml             //              this.txtoutputxml.dock = system.windows.forms.dockstyle.fill;             this.txtoutputxml.font = new system.drawing.font("lucida console", 7f, system.drawing.fontstyle.regular, system.drawing.graphicsunit.point, ((byte)(0)));             this.txtoutputxml.location = new system.drawing.point(3, 16);             this.txtoutputxml.maxlength = 1000000;             this.txtoutputxml.multiline = true;             this.txtoutputxml.name = "txtoutputxml";             this.txtoutputxml.scrollbars = system.windows.forms.scrollbars.both;             this.txtoutputxml.size = new system.drawing.size(383, 146);             this.txtoutputxml.tabindex = 1;             //              // frmxslttest             //              this.autoscaledimensions = new system.drawing.sizef(6f, 13f);             this.autoscalemode = system.windows.forms.autoscalemode.font;             this.clientsize = new system.drawing.size(788, 363);             this.controls.add(this.splitcontainer1);             this.name = "frmxslttest";             this.text = "frmxslttest";             this.splitcontainer1.panel1.resumelayout(false);             this.splitcontainer1.panel2.resumelayout(false);             ((system.componentmodel.isupportinitialize)(this.splitcontainer1)).endinit();             this.splitcontainer1.resumelayout(false);             this.groupbox1.resumelayout(false);             this.groupbox1.performlayout();             this.splitcontainer2.panel1.resumelayout(false);             this.splitcontainer2.panel2.resumelayout(false);             ((system.componentmodel.isupportinitialize)(this.splitcontainer2)).endinit();             this.splitcontainer2.resumelayout(false);             this.groupbox2.resumelayout(false);             this.groupbox2.performlayout();             this.groupbox3.resumelayout(false);             this.groupbox3.performlayout();             this.resumelayout(false);          }          #endregion          private system.windows.forms.splitcontainer splitcontainer1;         private system.windows.forms.button btntransform;         private system.windows.forms.groupbox groupbox1;         private system.windows.forms.textbox txtstylesheet;         private system.windows.forms.splitcontainer splitcontainer2;         private system.windows.forms.groupbox groupbox2;         private system.windows.forms.groupbox groupbox3;         private system.windows.forms.textbox txtinputxml;         private system.windows.forms.textbox txtoutputxml;     } } 

the form class (frmxslttest.cs):

using system; using system.collections.generic; using system.componentmodel; using system.data; using system.drawing; using system.linq; using system.text; using system.windows.forms;  using system.xml; using system.xml.xsl;  using xslttest.xml;  namespace xslttest {     public partial class frmxslttest : form     {         public frmxslttest()         {             initializecomponent();         }          private void btntransform_click(object sender, eventargs e)         {             try             {                 // temporary copy clipboard when pressing                  // button instead of using text in textbox                 //txtstylesheet.text = clipboard.gettext();                  xmldocument stylesheet = new xmldocument();                 stylesheet.innerxml = txtstylesheet.text;                  xslcompiledtransform xct = new xslcompiledtransform(true);                 xct.load(stylesheet);                  xmldocument inputdocument = new xmldocument();                 inputdocument.innerxml = txtinputxml.text;                  xmlstringwriter outputwriter = xmlstringwriter.create();                  xct.transform(inputdocument, outputwriter);                  txtoutputxml.text = outputwriter.tostring();             }              catch (exception ex)             {                 txtoutputxml.text = ex.message;             }         }     } } 

Comments

Popular posts from this blog

c# - SharpSVN - How to get the previous revision? -

c++ - Is it possible to compile a VST on linux? -

url - Querystring manipulation of email Address in PHP -