xml: get item's value, exclude comments from selection

rated by 0 users
This post has 13 Replies | 3 Followers

Top 50 Contributor
Posts 80
Bush Posted: 02-21-2012 2:18 AM

Hi All. I have xml file:


<?xml version="1.0" encoding="utf-8" ?>
    <variables>
        <!--My first variable-->
        <acsrv>%AppData%\MyCompanyName\MySoftName</acsrv>
        <!--My second variable-->
        <wproj>%AppData%\MyCompanyName\MySoftName</wproj>
    </variables>

I need for each 'variables' item create new environment variable (in user profile). I can't get value for xml item. My code:

# Current directory
$curDir = $MyInvocation.MyCommand.Definition | split-path -parent
# xml file full name
$xmlFile = "$curDir\variables.xml"
# Reed variables from xml file
$xmldata = [xml](Get-Content $xmlFile)
# Create or reset variables
$xmldata.variables foreach {[Environment]::SetEnvironmentVariable($_.Name, $_.Value, "User")}

1. What should I write instead of "$ _.Value"? 
2. How from sampling to eliminate objects of comments? 

I read it chapter, but haven't found the answer.

Sorry for my English
Regards

Top 25 Contributor
Posts 287
Top Contributor

Hi,

The easiest way is to re-structure your XML file.

<?xml version="1.0" encoding="utf-8" ?>
 <variables>
  <!--My first variable-->
  <name>acsrv</name>
   <value>%AppData%\MyCompanyName\MySoftName</value>
   <!--My second variable-->
  <name>wproj</name>
   <value>%AppData%\MyCompanyName\MySoftName</value>
 </variables>

Top 50 Contributor
Posts 80

Felipe:
The easiest way is to re-structure your XML file. 

I think that this bad problem resolution.

Top 25 Contributor
Posts 287
Top Contributor

Well and I think that is a bad XML file. But I'm here to help and not to criticize.

Anyway...

Another way to do it:

$xmldata = [xml](Get-Content $xmlFile)

$properties = $xmldata | Get-Member -MemberType property | select -ExpandProperty name

foreach($_ in $xml){[Environment]::SetEnvironmentVariable($_.($properties[1]), $_.($properties[2]), "user")}

Top 50 Contributor
Posts 80

Felipe:
Well and I think that is a bad XML file.

I would like to manage more laconic variant xml. At me many such files also will alter all of them not rationally. By means of LINQ to XML I easily work with any xml. I wouldn't like to start to edit xml only because PowerShell something can't make. :(((

Thanks for the code, but it don't work. Even if I will replace in a cycle ' foreach ' a name of unknown variable ' $xml ' on ' $xmldata ' all the same, as a result, I receive an error. The variable '$properties' as values contains ' variables ' and ' xml ', and it not those values which need to be selected.

Regards

Top 25 Contributor
Posts 287
Top Contributor

Sorry I missed something. Try this:

$xmldata = [xml](Get-Content $xmlFile)

$properties = $xmldata.variables | Get-Member -MemberType property | select -ExpandProperty name

for($i=1;$i -lt $properties.count; $i++){

if($properties[$i] -match "#comment"){$i++}

else{

[Environment]::SetEnvironmentVariable($_.($properties[$i]), $_.($properties[$i+1]), "user")}}

If you are consistent with your XML files this should work.

Top 50 Contributor
Posts 80

No, it not work too.


# Current directory
$curDir = $MyInvocation.MyCommand.Definition | split-path -parent
# xml file full name
$xmlFile = "$curDir\variables.xml"
# Reed variables from xml file
$xmldata = [xml](Get-Content $xmlFile)
$properties = $xmldata.variables | Get-Member -MemberType property | select -ExpandProperty name
for($i=1;$i -lt $properties.count; $i++){
  if($properties[$i] -match "#comment"){$i++}
  else{
    # Check values:
    $_.($properties[$i]) + " = " + $_.($properties[$i+1])  
    # [Environment]::SetEnvironmentVariable($_.($properties[$i]), $_.($properties[$i+1]), "user")
  }
}

I get it:


 =
 =

Top 25 Contributor
Posts 341
Top Contributor


I get it:

  =
  =

 

That suggests that the two Propertiies values are both blank!

Let me play some more...

 

Top 50 Contributor
Posts 80

>That suggests that the two Propertiies values are both blank!

It is incorrect. In the first message of this subject I have shown contents of the xml a file.

I successfully derive the data by means of XPath and XSLT:

Xml source file:

   1:  <?xml version="1.0" encoding="utf-8" ?>
   2:  <?xml-stylesheet type="text/xsl" href="xpath2.xsl"?>
   3:  <variables>
   4:          <!--My first variable-->
   5:          <acsrv>%AppData%\MyCompanyName\MySoftName</acsrv>
   6:          <!--My second variable-->
   7:          <wproj>%AppData%\MyCompanyName\MySoftName</wproj>
   8:  </variables>

 



XSLT file:

 

<?xml version="1.0"?>

<xsl:stylesheet version="1.0"

xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output encoding="UTF-8" method="text"/>

<xsl:template match="/">

<xsl:for-each select="/variables/child::*">

<xsl:value-of select="name()"/>

<xsl:text> = </xsl:text>

<xsl:value-of select="."/>

<xsl:text>&#xA;</xsl:text>

</xsl:for-each>

</xsl:template>

</xsl:stylesheet>

 

Result (if xml file open in browser):

acsrv = %AppData%\MyCompanyName\MySoftName
wproj = %AppData%\MyCompanyName\MySoftName

 

In PowerShell too it is used XPath, but at me it is impossible to pick up analog "." (point).

Regards

Top 25 Contributor
Posts 341
Top Contributor

OK - I've got two basic comments about this.

First, I can see what's happening. Your use of Get-Member transforms the XMLdata into simple strings, so what follows does indeed break. I think you want to just work with the XML Data.

Second, you expose some interesting aspects of XML handling in .NET!

So  let's star with the $xmldata. On my system, I see this:

Psh[Cookham8:C:\foo\xml]>$xmldata.variables

#comment                                              acsrv                                                wproj                                               
--------                                              -----                                                -----                                               
{My first variable, My second variable}               %AppData%\MyCompanyName\MySoftName                   %AppData%\MyCompanyName\MySoftName

Note that the two comments are somehow munged under the comment element.

 

A better way to do this, imho, would be by restructuring your XML as follows:

<?xml version="1.0" encoding="utf-8" ?>
    <variables>
        <variable>
          <!--My first variable-->
            <name>acsrv</name>
            <value>%AppData%\MyCompanyName\MySoftName</value>
        </variable>
        <variable>
            <!--My second variable-->
            <name>wproj</name>
            <value>%AppData%\MyCompanyName\MySoftName</value>
        </variable>
    </variables>

 

Doing this means you can do this:

$xmlFile = ".\variables2.xml"
$y = #comment

# Read variables from xml file
$xmldata = [xml](Get-Content $xmlFile)


Foreach ($var in $vars) {

$v = $var.($var.GetEnumerator().name[0])

" {0,-20}  name: {1,15} is being set to: {2}" -f  $v,$var.name, $var.value

[Environment]::SetEnvironmentVariable($var.name,$var.value, "user")
}

Now I'm sure there are better ways to do this, but it's Friday night and I'm wacked out!

 

In general though, while I am sure we could do it your way, the more verbose style of XML noted in this post is more in keeping with what I'd expect.

I hope this helps.

 

BTW: where areu based?

 

 

 

Top 25 Contributor
Posts 341
Top Contributor

Bush:

>That suggests that the two Propertiies values are both blank!

It is incorrect. In the first message of this subject I have shown contents of the xml a file.

 

In the cited code, the two property values were blank - I can duplicate your issue.

 

I'm not a wizzard at XML and I certainly do not pretend to know all there is to know about XML. But what I would have expected to see in an XML file would be more like this:

 

<?xml version="1.0" encoding="utf-8" ?>
    <variables>
        <variable>
            <comment>My first variable</comment>
            <name>acsrv</name>
            <value>%AppData%\MyCompanyName\MySoftName</value>
        </variable>
        <variable>
             <comment>My second variable</comment>
             <name>wproj</name>
             <value>%AppData%\MyCompanyName\MySoftName</value>
        </variable>
    </variables>

This is more typical of the XML I deal with where there's a formal schema and you don't have random tag name.  IMHO, the 'comment' is more a business comment and therefore is part of the  data being persisted in XML rather than an XML comment about the XML itself.

Hope this helps.


Thomas

Top 50 Contributor
Posts 80

Thomas Lee:
A better way to do this, imho, would be by restructuring your XML as follows

It is possible to change xml a file that it was easier to work with it. But I nevertheless would like to find the decision and for the given variant.

Today I was very tired. I will study your answer tomorrow in more details.

Thomas Lee:
BTW: where areu based?

I am from Saint Petersburg (Russia). 

Sorry for my English

Regards

Top 25 Contributor
Posts 341
Top Contributor

I'm just trying to help. I could probably wade into the xml and work out how to do it, but IMHO, the XML itself is not great XML. IMHO, you want XML to schematatized and the approach you are trying to use does not lend itself to being such).

There is at least a workable answer on the table. I hope this helps.

Welcome to from, in case i did not say so before - and your English is far better than my Russian!

 

Top 50 Contributor
Posts 80

Thanks :)

Page 1 of 1 (14 items) | RSS
Copyright 2012 PowerShell.com. All rights reserved.