locked
Help to understand why PsObject output has {$null, SomeValue} RRS feed

  • Question

  • Hello,

    I'm new to hashtables and PsObjects so some help is appreciated, I don't understand why it is doing this.  And I'm no expert powersheller so avoiding powershell shortcuts (and talking extra loud and slow) will help me understand what I'm doing wrong.  My output:

    $UserDetails
    
    UserName      : {$null, Bill.Gates@myDomain.com}
    UserLastName  : {$null, Gates}
    UserExpiresOn : {$null, 06/26/2019 02:03 PM}
    UserFirstName : {$null, Bill}
    UserEmail     : {$null, Bill.Gates@myDomain.com}

    I'm only expecting key/value pair, no $nulls or {}

    History

    Its a bit wordy.  So in short.  I have one file folder for each user.  In each folder is a file "user.xml", the XML contains the fields shown above (UserName, FirstName, etc).  Using powershell I've stored all those XML files (900+) into one $UserXmlData:

    $UserXmlData = @()
    foreach ( ... )
    {
      ...
      ...
      $UserXmlData += [Xml] (Get-Content -Path $FullFilename)
    }

    And now that I have all the XML data, I'm trying to build my own custom object where I can merge it with other data (group info)... I'm doing that by using:

    $AllDetails = @()
    
    foreach ($User in $UserXmlData)
    {
        $UserName      = $User.ChildNodes.username
        $UserEmail     = $User.ChildNodes.email
        $UserFirstName = $User.ChildNodes.first_name
        $UserLastName  = $User.ChildNodes.last_name
        $UserExpiresOn = $User.ChildNodes.account_expire
    
        $UserDetails       = New-Object -TypeName PSObject -Property @{
            UserName       = $UserName
            UserEmail      = $UserEmail
            UserFirstName  = $UserFirstName
            UserLastName   = $UserLastName
            UserExpiresOn  = $UserExpiresOn
        }
        $AllDetails += $UserDetails
    }


    If I output $UserName, the expected value is shown, so I'm not sure where the extra "column" is coming from when it is put into the PsObject.  If you're going to say $null cant be displayed, I understand, by why is it displayed in the PsObject output?

    $UserName
    Bill.Gates@myDomain.com
    
    and...
    
    $UserName | ft
    Bill.Gates@myDomain.com

    Maybe I need to trim, or convert to a string, or have a nap.  I don't know anymore, is it Friday yet?


    • Edited by Drew.Prince Wednesday, August 7, 2019 10:09 PM correct terminology
    Wednesday, August 7, 2019 10:09 PM

Answers

  • I have found that using this syntax has worked better for my use and gets rid of the odd behavior I was seeing.

    $User.userfile.username

    • Marked as answer by Drew.Prince Friday, August 9, 2019 10:31 PM
    Friday, August 9, 2019 10:31 PM

All replies

  •   $UserName      =$User.ChildNodes.username.'#text'


    \_(ツ)_/

    Wednesday, August 7, 2019 10:36 PM
  • Jrv, in a way you can understand...

    $UserDetails


    UserName      :
    UserLastName  :
    UserExpiresOn :
    UserFirstName :
    UserEmail     :

    Thursday, August 8, 2019 1:10 AM
  • Or to add significant more detail.

    $User.ChildNodes.username
    Bill.Gates@myDomain.com

    Which you knew already... and when I use this command:

    $User.ChildNodes.username.'#text'

    The result is below this line.  Really.

    Thursday, August 8, 2019 1:13 AM
  • Without a sample of the XML there is no way to guess exactly. XML can have a namespace that is required or the tags could be attributes that are handled differently.


    \_(ツ)_/

    Thursday, August 8, 2019 1:14 AM
  • Ah ok. Here is a sample of one of the users XML file.

    <?xml version="1.0" encoding="UTF-8"?>
    <userfile type="properties">
     <email>Bill.Gates@myDomain.com</email>
     <username>Bill.Gates@myDomain.com</username>
     <account_expire>06/26/2019 02:03 PM</account_expire>
     <version>1.0</version>
     <first_name>Bill</first_name>
     <user_name>Bill.Gates@myDomain.com</user_name>
     <last_name>Gates</last_name>
    </userfile>

    Thursday, August 8, 2019 1:20 AM
  • I cannot reproduce your problem with that XML.

    [xml]$xml = @'
    <?xml version="1.0" encoding="UTF-8"?>
     <userfile type="properties">
      <email>Bill.Gates@myDomain.com</email>
      <username>Bill.Gates@myDomain.com</username>
      <account_expire>06/26/2019 02:03 PM</account_expire>
      <version>1.0</version>
      <first_name>Bill</first_name>
      <user_name>Bill.Gates@myDomain.com</user_name>
      <last_name>Gates</last_name>
     </userfile>
    '@
    D:\scripts> $xml.username
    D:\scripts> $xml.userfile.user_name
    Bill.Gates@myDomain.com
    D:\scripts> $xml.userfile.username
    Bill.Gates@myDomain.com
    D:\scripts> $username = $xml.userfile.username
    D:\scripts> $username
    Bill.Gates@myDomain.com
    D:\scripts>
    Perhaps you should use standard methods and not try to be fancy with "ChildNodes".


    \_(ツ)_/



    • Edited by jrv Thursday, August 8, 2019 1:28 AM
    Thursday, August 8, 2019 1:26 AM
  • Note that you cannot concatenate XML files as you ae doing:

     $UserXmlData += [Xml] (Get-Content -Path $FullFilename)
    This will corrupt the XML.


    \_(ツ)_/

    Thursday, August 8, 2019 1:31 AM
  • You mentioned "this will corrupt the XML". Could you elaborate more please?

    I'm not trying to write back to any XML file, only gather data from XML files and store in PowerShell variables/objects. 

    Thursday, August 8, 2019 2:27 AM
  • As I mentioned I am new to hashtables and psobjects. I am not trying to be fancy, I am just trying different methods from what I have read about.

    As the title of this topic says... I am trying to help understand.  If you can point in a method or term to study I would be more than happy to read about it and try to figure it out on my own.  But it seems you're just jumping to provide a one line answer to solve it all by yourself.

    Thursday, August 8, 2019 2:31 AM
  • Nothing to explain.  You can't add the contents of XML files together like you are doing. You can only load one XML file at a time.


    \_(ツ)_/

    Thursday, August 8, 2019 2:35 AM
  • Ok, thank you for your opinions.


    This command: $UserXmlData.ChildNodes.username

    Results in showing all 904 usernames collected from all 904 individual XML files.  All other values in the XML files are also displayed as expected.

    Thursday, August 8, 2019 2:42 AM
  • Actually you are just adding XML files to an array. That will work but it is not necessary.

    The bigger issue is that you cannot access the XML the way you are.  You need to do what I did which is to directly access node.  If the XML has multiple nodes of the same name then you will get an array of results.

    The example you posted does not match the issue you are asking about because it does not have multiple nodes of the same name and has no implied arrays.


    \_(ツ)_/

    Thursday, August 8, 2019 2:43 AM
  • Ok, thank you for your opinions.


    This command: $UserXmlData.ChildNodes.username

    Results in showing all 904 usernames collected from all 904 individual XML files.  All other values in the XML files are also displayed as expected.

    If that is what you want.  That is not what you asked about.

    \_(ツ)_/

    Thursday, August 8, 2019 2:44 AM
  • As I mentioned I am new to hashtables and psobjects. I am not trying to be fancy, I am just trying different methods from what I have read about.

    As the title of this topic says... I am trying to help understand.  If you can point in a method or term to study I would be more than happy to read about it and try to figure it out on my own.  But it seems you're just jumping to provide a one line answer to solve it all by yourself.

    You need to learn PowerShell and XML and how PowerShell works with the complex objects that you are trying to use.

    You can get the basics of XML here: https://www.w3schools.com/xml/default.asp


    \_(ツ)_/

    Thursday, August 8, 2019 2:46 AM
  • Ok, thank you for your opinions.


    This command: $UserXmlData.ChildNodes.username

    Results in showing all 904 usernames collected from all 904 individual XML files.  All other values in the XML files are also displayed as expected.

    Its not n opinion,. I have worked with XML for 30 years and with PowerShell since the first public beta.  I have also programmed in most major languges on multiple operating systems from mainframes to embedded systems.

    It is not an opinion.


    \_(ツ)_/

    Thursday, August 8, 2019 2:48 AM
  • I have found that using this syntax has worked better for my use and gets rid of the odd behavior I was seeing.

    $User.userfile.username

    • Marked as answer by Drew.Prince Friday, August 9, 2019 10:31 PM
    Friday, August 9, 2019 10:31 PM
  • Yes - that is what I showed you above very explicitly.  You must use the correct methods and have the correct understanding of XML and PowerShell with the XML type.


    \_(ツ)_/

    Friday, August 9, 2019 10:47 PM