Skip to content

Commit

Permalink
improvements, formatting
Browse files Browse the repository at this point in the history
handle null key names,
  • Loading branch information
msftrncs committed May 12, 2019
1 parent 14752e7 commit adf3242
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 23 deletions.
43 changes: 22 additions & 21 deletions PList Reader.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
Convert a XML Plist to a PowerShell object
.DESCRIPTION
Converts an XML PList (property list) in to a usable object in PowerShell.
Properties will be converted in to ordered hashtables, the values of each property may be integer, double, date/time, boolean, string, or hashtables, arrays of any these, or arrays of bytes.
.EXAMPLE
$pList = [xml](get-content 'somefile.plist') | ConvertFrom-Plist
.PARAMETER plist
The property list as an [XML] document object, to be processed. This parameter is mandatory and is accepted from the pipeline.
.INPUTS
plist - as an [XML] object containing the PList
system.xml.document
.OUTPUTS
[object] - containing the PList as conventional PowerShell object types, hashtables, arrays, strings, numeric values, and byte arrays.
system.object
.NOTES
Script / Function / Class assembled by Carl Morris, Morris Softronics, Hooper, NE, USA
Initial release - Aug 27, 2018
Expand All @@ -20,10 +24,8 @@
function ConvertFrom-Plist {
Param(
# parameter to pass input via pipeline
[Parameter(Mandatory = $true,
Position = 0,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
[Parameter(Mandatory, Position = 0,
ValueFromPipeline, ValueFromPipelineByPropertyName,
HelpMessage = 'XML Plist object.')]
[ValidateNotNullOrEmpty()]
[xml]$plist
Expand All @@ -40,14 +42,15 @@ function ConvertFrom-Plist {
if ($node.HasChildNodes) {
switch ($node.Name) {
dict {
# for dictionary, return the subtree as a hashtable, with possible recursion of additional arrays or dictionaries
# for dictionary, return the subtree as a ordered hashtable, with possible recursion of additional arrays or dictionaries
$collection = [ordered]@{}
$currnode = $node.FirstChild # start at the first child node of the dictionary
while ($null -ne $currnode) {
if ($currnode.Name -eq 'key') {
# a key in a dictionary, add it to a collection
if ($null -ne $currnode.NextSibling) {
$collection[[plistreader]::processTree($currnode.FirstChild)] = [plistreader]::processTree($currnode.NextSibling)
# note: keys are forced to [string], insures a $null key is accepted
$collection[[string][plistreader]::processTree($currnode.FirstChild)] = [plistreader]::processTree($currnode.NextSibling)
$currnode = $currnode.NextSibling.NextSibling # skip the next sibling because it was the value of the property
}
else {
Expand All @@ -64,7 +67,7 @@ function ConvertFrom-Plist {
}
array {
# for arrays, recurse each node in the subtree, returning an array (forced)
, @(foreach ($sibling in $node.ChildNodes) {[plistreader]::processTree($sibling)})
, @($node.ChildNodes.foreach{ [plistreader]::processTree($_) })
continue
}
string {
Expand All @@ -74,21 +77,19 @@ function ConvertFrom-Plist {
}
integer {
# must be an integer type value element, return its value
[plistreader]::processTree($node.FirstChild) | ForEach-Object {
[plistreader]::processTree($node.FirstChild).foreach{
# try to determine what size of interger to return this value as
if ([int]::TryParse( $_, [ref]$null)) {
# a 32bit integer seems to work
$_ -as [int]
}
elseif ([int64]::TryParse( $_, [ref]$null)) {
# a 64bit integer seems to be needed
$_ -as [int64]
}
else {
if ([int64]::TryParse( $_, [ref]$null)) {
# a 64bit integer seems to be needed
$_ -as [int64]
}
else {
# try an unsigned 64bit interger, the largest available here.
$_ -as [uint64]
}
# try an unsigned 64bit interger, the largest available here.
$_ -as [uint64]
}
}
continue
Expand Down Expand Up @@ -117,9 +118,9 @@ function ConvertFrom-Plist {
else {
# return simple element value (need to check for Boolean datatype, and process value accordingly)
switch ($node.Name) {
true {$true; continue} # return a Boolean TRUE value
false {$false; continue} # return a Boolean FALSE value
default {$node.Value} # return the element value
true { $true; continue } # return a Boolean TRUE value
false { $false; continue } # return a Boolean FALSE value
default { $node.Value } # return the element value
}
}
)
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ PowerShell function to process an XML PList file in to a meaningful object. The

Within it is a fairly complete XML PList reading function. The XML PList is a poorly constructed XML document, due to its <dict> items not being individually stored in separate 'property' child nodes.

The script presently accepts input of an XML object which it can accept from the pipeline. Use the [xml] shortcut to read the document:
The script presently accepts input of an XML object which it can accept from the pipeline. Use the \[xml\] shortcut to read the document:

```powershell
. '.\PList Reader.ps1'
$pList = [xml](get-content 'somefile.plist') | ConvertFrom-Plist
$grammar_plist = [xml](Get-Content PowerShellSyntax.tmLanguage) | ConvertFrom-Plist
```

Note:
- The overall script is still a work in progress, to properly define parameters, or even the overall function name.
- This function was initially developed to aid in processing TextMate tmLanguage grammar files.
- There is a possibility that not all PLIST documents can be handled at this time. `<key>` is not currently handled at the root level.

0 comments on commit adf3242

Please sign in to comment.