0

I need to Compare new names with name in XML file if name doesn't match then I would like to remove that actor from XML file, if the name doesn't existed then I would like to add it in.

$file = [xml]@'
<?xml version="1.0"?>
<data>
    <title>Name</title>
    <date>2019 Jan 01</date>
    <actor>
        <name>Actor Name 1</name>
        <type>Actor</type>
        <thumb>image.jpg</thumb>
    </actor>

    <actor>
        <name>Actor Name 2</name>
        <type>Actor</type>
        <thumb>image.jpg</thumb>
    </actor>

    <genre>genre1</genre>
    <genre>genre2</genre>
</data>
'@

I try below code but it doesn't work

    $file = New-Object System.Xml.XmlDocument
    $file.Load($file_path)
    $file_data=$file.DocumentElement
    
   $oldarray =  $file_data.actor
    $newarray=@(
        "Actor 3",
        "Actor Name 1"
        )
    
    Compare-Object -IncludeEqual -ReferenceObject $oldArray -DifferenceObject $newarray | Where-Object  {
        $w=$_.InputObject
        
        if($_.SideIndicator -eq "=>"){
            $a = $file_data.appendChild($file.CreateElement("actor"))
            $a.AppendChild($file.CreateElement("name")).InnerText=$w.Trim()
            $a.AppendChild($file.CreateElement("type")).InnerText="Actor"
        }
    
        if($_.SideIndicator -eq "<="){
            $file_data.SelectSingleNode("//actor[text()='$w']") | foreach {[void]$_.parentnode.removechild($_)}
    
       }
    }

1 Answer 1

1

Start by removing <actor> nodes where the <name> is not in the list of new names:

$file = New-Object System.Xml.XmlDocument
$file.Load($file_path)
$file_data=$file.DocumentElement

$newNames = @(
  "Actor 3"
  "Actor Name 1"
)

# Use XPath to select all <name> nodes nested under an <actor> node
$existingNameNodes = $file.SelectNodes('//actor/name') 

# Filter against the list of new names
$removableNameNodes = $existingNameNodes |Where-Object InnerText -notin $newNames

$removableNameNodes |ForEach-Object {
    # Resolve parent <actor> node
    $actor = $_.ParentNode
    # Remove <actor> from its own parent
    $actor.ParentNode.RemoveChild($actor) |Out-Null
}

Now we just need to add the ones not already in the list:

$existingNameNodes = $file.SelectNodes('//actor/name') 

# Filter the new list against the existing names
$namesToAdd = $newNames |Where-Object { $_ -notin $existingNameNodes.InnerText }

foreach($name in $namesToAdd){
    # Create new <actor> and <name> nodes
    $newActorNode = $file.CreateElement('actor')
    $newActorName = $file.CreateElement('name')
    $newActorName.InnerText = $name

    # Nest new <name> under new <actor>, nest <actor> under <data> 
    $file.data.AppendChild(
        $newActor.AppendChild(
            $newActorName
        )
    ) |Out-Null
}
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you this worked. I change the add to this. $a = $file_data.appendChild($file.CreateElement("actor")) $a.AppendChild($file.CreateElement("name")).InnerText=$name.Trim() $a.AppendChild($file.CreateElement("type")).InnerText="Actor"
@maj That's great, you're welcome! Please consider marking my answer "accepted" if it solves your problem
On some actors it removing them and then adding them backing again. I cant see the name being different
@maj Sorry, I omitted calling $file.SelectNodes('//actor/name') again. Updated the answer
I had a space in some actors name but I was using Trim to remove any extra white space. Thank you for all your work

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.