2

see the following xml

    <catalog>
        <books>
           <book id="bk101">
              <author>Gambardella, Matthew</author>
              <title>XML Developer's Guide</title>
              <genre>Computer</genre>
              <price>44.95</price>
              <publish_date>2000-10-01</publish_date>
              <description>An in-depth look at creating applications 
              with XML.</description>
           </book>
           <book id="bk102">
              <author>Ralls, Kim</author>
              <title>Midnight Rain</title>
              <genre>Fantasy</genre>
              <price>5.95</price>
              <publish_date>2000-12-16</publish_date>
              <description>A former architect battles corporate zombies, 
              an evil sorceress, and her own childhood to become queen 
              of the world.</description>
           </book>
           <book id="bk103">
              <author>Corets, Eva</author>
              <title>Maeve Ascendant</title>
              <genre>Fantasy</genre>
              <price>5.95</price>
              <publish_date>2000-11-17</publish_date>
              <description>After the collapse of a nanotechnology 
              society in England, the young survivors lay the 
              foundation for a new society.</description>
           </book>
       </books>
    </catalog>

I want to, in powershell, select the book node/element where the author is Corets,Eva and then add a child element of book, another element(sibling of price, comes directly after price) of , say, length. along with a new value for length of say, '456'

So the (partial) xml code for the book element after Ive run the code would look like:

<catalog>
    <books>
       <book id="bk103">
          <author>Corets, Eva</author>
          <title>Maeve Ascendant</title>
          <genre>Fantasy</genre>
          <price>5.95</price>
          <length>456</length>        
          <publish_date>2000-11-17</publish_date>
          <description>After the collapse of a nanotechnology 
          society in England, the young survivors lay the 
          foundation for a new society.</description>
       </book>
       <book>
        ....
       </book>
    </books>
<etc>

Can anyone assist? Been stuck for two days now. Thanks

1
  • 1
    Please add the code of what you have tried so far, including any (incorrect) output. Commented Nov 17, 2021 at 14:45

2 Answers 2

2

You can use the XMLNode.InsertAfter method.

Example:

[xml]$books = Get-Content .\books.xml
$corets = $books.catalog.books.book | Where-Object { $_.author -eq 'Corets, Eva' }
$coretsPrice = $corets.SelectSingleNode('price')
$coretsLength = $books.CreateElement('length')
$coretsLength.InnerText = 495
$corets.InsertAfter($coretsLength, $coretsPrice)
Sign up to request clarification or add additional context in comments.

1 Comment

I put a thanks comment in here yesterday but for some reason its disappeared. So again, many thanks, works a treat!
1

You can use the following XPath expression to select only <book /> nodes where a child node <author> has a text value of Corets, Eva:

//book[author[. = 'Corets, Eva']]

So you could do something like:

# Create a new XML document
$newDocument = [xml]'<catalog><books></books></catalog>'
$newBooks = $newDocument.SelectSingleNode('/catalog/books')

# Loop through all relevant <book> nodes in the existing document
foreach($book in $existingDocument.SelectNodes('//book[author[. = 'Corets, Eva']]')){
    # import book node to new document
    $newBook = $newDocument.ImportNode($book, $true)

    # add new required child node
    $newLength = $newDocument.CreateElement('length')
    $newLength.InnerText = '456'

    # insert new node after `price`
    [void]$newBook.InsertAfter($newLength, $newBook.SelectSingleNode('./price'))
    # insert new book node under /catalog/books
    [void]$newBooks.AppendChild($newBook)
}

1 Comment

Many thanks Mathias, went with dugas solution as it got here first and worked. But yours looks great also.

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.