简体   繁体   中英

Xml parsing in powershell:Adding and removing

I am trying to add and remove entries from xml file using powershell. This is how my xml file content looks like.

<?xml version="1.0" encoding="UTF-8"?>
<jdbc-data-source>
  <name>namevalue</name>
  <jdbc-driver-params>
    <url>connval</url>
    <driver-name>DriverVal</driver-name>
    <properties>
      <property>
        <name>user</name>
        <value>username</value>
      </property>
    </properties>
    <password-encrypted>encryptedpwd</password-encrypted>
  </jdbc-driver-params>
</jdbc-data-source>

I need to remove encryptedpwd entry and add unencryptedpwd

I have been trying with following piece of code.


$file = "Path of xml file with content as mentioned above"
Get-ChildItem $file | % {
    [Xml]$xml = Get-Content $_.FullName

    $addItem = $xml.CreateElement('password')
    $addItem.PsBase.InnerText = 'unencryptedpwd'
    $xml.'jdbc-data-source'.'jdbc-driver-params'.AppendChild($addItem) | Out-Null

    $nodes = $xml.'jdbc-data-source'.'jdbc-driver-params'
    $nodes | % {
        $child_node = $_.SelectSingleNode('password-encrypted')
        $_.RemoveChild($child_node) | Out-Null
    }
    $xml.OuterXml | Out-File $_.FullName
}

It has got following problems.

  1. It does not remove the child 'password-encrypted'.

  2. It removes all newline breaks.

Can anyone help on this, please?

First, your sample xml isn't well formed - the root element needs to be properly closed: the bottom <jdbc-data-source> should be </jdbc-data-source> .

Assuming that's fixed, you need to parse the xml using the xml parser, and use xpath to locate, delete and insert your elements.

So, if I understand you correclty, this should work:

$xml=[Xml]@"
[your xml above, fixed]

"@
$newpass=@'

     <password>unencryptedpwd</password>

'@
#locate the element to delete
$node = $xml.SelectSingleNode('//password-encrypted') 
#go to its parent and delete the child
$dest = $node.ParentNode
$dest.RemoveChild($node)
#import the new element as a fragment
$xmlFragment=$xml.CreateDocumentFragment()
$xmlFragment.InnerXML=$newpass
#finally, insert it in the xml
$dest.AppendChild($xmlFragment)

The modified xml should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<jdbc-data-source>
  <name>namevalue</name>
  <jdbc-driver-params>
    <url>connval</url>
    <driver-name>DriverVal</driver-name>
    <properties>
      <property>
        <name>user</name>
        <value>username</value>
      </property>
    </properties>
     <password>unencryptedpwd</password>
</jdbc-driver-params>
</jdbc-data-source>

Another but similar approach is like below:

[xml]$xml = @'
<?xml version="1.0" encoding="UTF-8"?>
<jdbc-data-source>
  <name>namevalue</name>
  <jdbc-driver-params>
    <url>connval</url>
    <driver-name>DriverVal</driver-name>
    <properties>
      <property>
        <name>user</name>
        <value>username</value>
      </property>
    </properties>
    <password-encrypted>encryptedpwd</password-encrypted>
  </jdbc-driver-params>
</jdbc-data-source>
'@

# remove the 'password-encrypted' node
$node = $xml.SelectSingleNode('//password-encrypted')
[void]$node.ParentNode.RemoveChild($node)

# create and add the new 'unencryptedpwd' node
$newNode = $xml.CreateElement('unencryptedpwd')
$newNode.InnerText = 'your unencrypted password'
[void]$xml.'jdbc-data-source'.'jdbc-driver-params'.AppendChild($newNode)

$xml.Save('D:\Test\test.xml')

PS There is a better way to load the xml than using Get-Content that automatically takes the documents encoding into account:

# load the xml file. This way, you are ensured to get the file encoding correct
$xml = [System.Xml.XmlDocument]::new()
$xml.Load($_.FullName)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM