Xml 根据子元素的值查找主元素,然后更改不同子元素的值
我有一个具有以下结构的xml文件:Xml 根据子元素的值查找主元素,然后更改不同子元素的值,xml,powershell,Xml,Powershell,我有一个具有以下结构的xml文件: <PARENT> <LIBRARY> <BOOKS> <BOOK> <BOOK_DATA> <BOOK_TITLE>HOBBIT</BOOK_TITLE> </BOOK_DATA> &
<PARENT>
<LIBRARY>
<BOOKS>
<BOOK>
<BOOK_DATA>
<BOOK_TITLE>HOBBIT</BOOK_TITLE>
</BOOK_DATA>
<STATUS>NotRead</STATUS>
</BOOK>
<BOOK>
<BOOK_DATA>
<BOOK_TITLE>LOTR_FOTR</BOOK_TITLE>
</BOOK_DATA>
<STATUS>NotRead</STATUS>
</BOOK>
<BOOK>
<BOOK_DATA>
<BOOK_TITLE>LOTR_TT</BOOK_TITLE>
</BOOK_DATA>
<STATUS>NotRead</STATUS>
</BOOK>
<BOOK>
<BOOK_DATA>
<BOOK_TITLE>LOTR_ROTK</BOOK_TITLE>
</BOOK_DATA>
<STATUS>NotRead</STATUS>
</BOOK>
</BOOKS>
</LIBRARY>
</PARENT>
我建议按标记名查找元素。然后,您需要在层次结构的更高层次上访问书籍的相应状态 然后很容易设置状态
$foundedElement = $test.GetElementsByTagName("BOOK_TITLE") |Where-Object {$_."#text" -eq $BookTitle}
$foundedElement.ParentNode.ParentNode.STATUS = $NewStatus
$test.Save($fileName)
我建议按标记名查找元素。然后,您需要在层次结构的更高层次上访问书籍的相应状态 然后很容易设置状态
$foundedElement = $test.GetElementsByTagName("BOOK_TITLE") |Where-Object {$_."#text" -eq $BookTitle}
$foundedElement.ParentNode.ParentNode.STATUS = $NewStatus
$test.Save($fileName)
我建议对此问题使用
XPath
:
[xml]$xml = ' ... '
$bookTitle = 'LOTR_TT'
$newStatus = 'Read'
$node = $xml.SelectSingleNode("//BOOK[BOOK_DATA/BOOK_TITLE='$bookTitle']/STATUS")
$node.'#text' = $newStatus
这里的重要部分是过滤器:
//BOOK[BOOK_DATA/BOOK_TITLE='$bookTitle']/STATUS
这将从与筛选器book\u TITLE='$bookTitle'
匹配的书籍中选择STATUS
节点,powershell将InnerText
作为\text
属性公开
在示例脚本中使用:
param(
[string]
$BookTitle = 'LOTR_TT',
[string]
$NewStatus = 'Read',
[string]
$FilePath = 'C:\file.xml'
)
[xml]$xml = Get-Content -Path $FilePath
$node = $xml.SelectSingleNode("//BOOK[BOOK_DATA/BOOK_TITLE='$BookTitle']/STATUS")
$node.'#text' = $NewStatus
$xml.Save($FilePath)
或者,如果要查找包含要更改为读取的字符串的所有节点,可以执行以下操作:
$xml.SelectNodes("//BOOK[BOOK_DATA/BOOK_TITLE[contains(., '$BookTitle')]]/STATUS") |
ForEach-Object { $_.'#text' = $NewStatus }
我建议对此问题使用
XPath
:
[xml]$xml = ' ... '
$bookTitle = 'LOTR_TT'
$newStatus = 'Read'
$node = $xml.SelectSingleNode("//BOOK[BOOK_DATA/BOOK_TITLE='$bookTitle']/STATUS")
$node.'#text' = $newStatus
这里的重要部分是过滤器:
//BOOK[BOOK_DATA/BOOK_TITLE='$bookTitle']/STATUS
这将从与筛选器book\u TITLE='$bookTitle'
匹配的书籍中选择STATUS
节点,powershell将InnerText
作为\text
属性公开
在示例脚本中使用:
param(
[string]
$BookTitle = 'LOTR_TT',
[string]
$NewStatus = 'Read',
[string]
$FilePath = 'C:\file.xml'
)
[xml]$xml = Get-Content -Path $FilePath
$node = $xml.SelectSingleNode("//BOOK[BOOK_DATA/BOOK_TITLE='$BookTitle']/STATUS")
$node.'#text' = $NewStatus
$xml.Save($FilePath)
或者,如果要查找包含要更改为读取的字符串的所有节点,可以执行以下操作:
$xml.SelectNodes("//BOOK[BOOK_DATA/BOOK_TITLE[contains(., '$BookTitle')]]/STATUS") |
ForEach-Object { $_.'#text' = $NewStatus }
据我所知,您的代码中有两个错误:
$booktile
和$NewStatus
的值,使它们成为$BookTitle='LOTR\u TT'
和$NewStatus='Read'
$。STATUS='$NewStatus'
,通过这样做,您可以将STATUS设置为“$NewStatus”的literal值。删除这些引号以插入变量的值:
$\状态=$NewStatus
在那之后,if对我来说很好。据我所知,您的代码中有两个错误:
$booktile
和$NewStatus
的值,使它们成为$BookTitle='LOTR\u TT'
和$NewStatus='Read'
$。STATUS='$NewStatus'
,通过这样做,您可以将STATUS设置为“$NewStatus”的literal值。删除这些引号以插入变量的值:
$\状态=$NewStatus
之后,if对我很有效。当引用
$BookTitle
和$NewStatus
的值时,它对我有效。。如果未加引号,则会产生错误:术语“LOTR\u TT”无法识别为cmdlet、函数、脚本文件或可操作程序的名称。
。这是您意外的结果吗?当引用$BookTitle
和$NewStatus
的值时,它对我有效。。如果未加引号,则会产生错误:术语“LOTR\u TT”无法识别为cmdlet、函数、脚本文件或可操作程序的名称。
。这是你意想不到的结果吗?