【问题标题】:Grouping the elements inside the XML based on Attribute value根据属性值对 XML 中的元素进行分组
【发布时间】:2021-09-02 00:29:05
【问题描述】:

我有一个如下所示的 xml 文件

   <Books>
 <Book rev="19ver" nver="1.0.0.0" >
<Book rev="19Sub4" nver="1.4.0.250">
  <Book rev="19Sub5" nver="1.5.0.250" >
     <Book rev="19Sub5Fix2" nver="1.5.2.250" req="true">
    </Book>
    <Book rev="19Sub5Fix1" nver="1.5.1.250" req="false">
    </Book>
  </Book>
</Book>
<Book rev="20ver" nver="2.0.0.0" >
 <Book rev="20Sub3" nver="2.3.0.1111">
<Book rev="20Sub3Fix5" nver="2.3.5.1111"  req="true" >
</Book>
<Book rev="20Sub3Fix4" nver="2.3.4.1111"  req="true" >
</Book>
 <Book rev="20Sub3Fix3" nver="2.3.3.1111"  req="false" >
</Book>
<Book rev="20Sub3Fix2" nver="2.3.2.1111"  req="false" >
</Book>
<Book rev="20Sub4" nver="2.4.0.1567" >
  <Book rev="20Sub4Fix5" nver="2.4.5.1567"  req="true" >
  </Book>
  <Book rev="20Sub4Fix4" nver="2.4.4.1567"  req="true" >
  </Book>
  <Book rev="20Sub4Fix3" nver="2.4.3.1567"  req="false" >
  </Book>
  <Book rev="20Sub4Fix2" nver="2.4.2.1567"  req="false" >
  </Book>
   <Book rev="20Sub4Fix1" nver="2.4.1.1567"  req="false" >
    </Book>
    </Book>
 </Book>
 </Book>
 </Book>
 </Books>

我有一个 powershell 脚本来在指定节点内添加一个新元素。例如,如果我想在“20Sub3”中输入带有rev“20Sub3Fix6”和nver“2.3.6.1111”的元素,我可以使用以下代码。

$parentXML = Select-Xml -Xml $bookInfo -XPath "//*[@rev='20Sub3']"
$bookInfo = Get-Content -Raw -Path $XMLPATH
$book = $bookInfo.CreateNode("element","book","")             
$book.SetAttribute("rev","20Sub3Fix6")
$book.SetAttribute("nver","2.3.6.1111")
$book.SetAttribute("req","true")
$rslt = $parentXML.Node.prependChild($book)
$bookInfo.Save($XMLPATH)

我正在寻找的是根据属性“req”的值对元素进行分组。当我添加一个带有req“false”的元素时,它应该添加到最后一个元素的顶部,并带有“req = false”。此外,当我添加一个带有req“true”的元素时,它应该添加到最后一个带有“req”的元素之上=真”。

<Book rev="20Sub1" nver="2.1.0.769" >
   <Book rev="20Sub1Fix7" nver="2.1.7.769" req="true"  >
  </Book>
  <Book rev="20Sub1Fix6" nver="2.1.6.769"  req="true" >
  </Book>
  <Book rev="20Sub1Fix4" nver="2.1.4.769"  req="true" >
  </Book>
  <Book rev="20Sub1Fix3" nver="2.1.3.769"  req="false" >
  </Book>
  <Book rev="20Sub1Fix2" nver="2.1.2.769"  req="false" >
  </Book>
  <Book rev="20Sub1Fix1" nver="2.1.1.769"  req="false" >
  </Book>
 </Book>

添加 C# 和 .Net 标记也是因为如果您知道 C# 中的答案,那么您也可以发布它

【问题讨论】:

  • 使用 Add 做最后,使用 AddFirst 做第一个。
  • 谢谢,但是如果新添加的元素有“req=true”,那么它应该添加到所有带有“req=true”的元素的顶部。此外,如果“req=false”,那么所有元素的顶部都是“req=false”。在上面的示例中,您可以看到如何添加“20Sub1Fix7”和“20Sub1Fix3”。不要只是把它放在最后或第一个
  • 为什么顺序很重要?顺便说一句,您显示的 XML 无效..
  • 当您说“在最后一个元素之上”时,您实际上是指“在第一个元素之前”吗?
  • yes 在最后一个元素之前,还要考虑“req”的值

标签: c# .net xml powershell


【解决方案1】:

我已格式化您的 XML 以便更好地理解其格式:

<Books>
  <Book rev="19ver" nver="1.0.0.0" >
    <Book rev="19Sub4" nver="1.4.0.250">
      <Book rev="19Sub5" nver="1.5.0.250" >
        <Book rev="19Sub5Fix2" nver="1.5.2.250" req="true"></Book>
        <Book rev="19Sub5Fix1" nver="1.5.1.250" req="false"></Book>
      </Book>
    </Book>
    <Book rev="20ver" nver="2.0.0.0" >
      <Book rev="20Sub3" nver="2.3.0.1111">
        <Book rev="20Sub3Fix5" nver="2.3.5.1111"  req="true" ></Book>
        <Book rev="20Sub3Fix4" nver="2.3.4.1111"  req="true" ></Book>
        <Book rev="20Sub3Fix3" nver="2.3.3.1111"  req="false" ></Book>
        <Book rev="20Sub3Fix2" nver="2.3.2.1111"  req="false" ></Book>
        <Book rev="20Sub4" nver="2.4.0.1567" >
          <Book rev="20Sub4Fix5" nver="2.4.5.1567"  req="true" ></Book>
          <Book rev="20Sub4Fix4" nver="2.4.4.1567"  req="true" ></Book>
          <Book rev="20Sub4Fix3" nver="2.4.3.1567"  req="false" ></Book>
          <Book rev="20Sub4Fix2" nver="2.4.2.1567"  req="false" ></Book>
          <Book rev="20Sub4Fix1" nver="2.4.1.1567"  req="false" ></Book>
        </Book>
      </Book>
    </Book>
  </Book>
</Books>

要做你想做的事,你可以使用下面的代码:

# load the xml from file
$xml= New-Object System.XML.XMLDocument
$xml.Load("D:\Test\MyBooks.xml")

# create your new node
$newNode = $xml.CreateElement("Book")
$newNode.SetAttribute("rev", "20Sub3Fix6")
$newNode.SetAttribute("nver", "2.3.6.1111")
$newNode.SetAttribute("req", "true")

# get the parentnode to insert the new node in
$node20Sub3   = $xml.SelectSingleNode("//Book[@rev='20Sub3']")
# find the first node where attribute 'req' is 'true'
$insertBefore = ($node20Sub3.ChildNodes | Where-Object { $_.rev.StartsWith("20Sub3Fix") -and $_.req -eq 'true' })[0]
# insert your new node on top of that
$node20Sub3.InsertBefore($newNode, $insertBefore)

# save the XML
$xml.Save("D:\Test\MyBooks.xml")

结果:

<Books>
  <Book rev="19ver" nver="1.0.0.0">
    <Book rev="19Sub4" nver="1.4.0.250">
      <Book rev="19Sub5" nver="1.5.0.250">
        <Book rev="19Sub5Fix2" nver="1.5.2.250" req="true"></Book>
        <Book rev="19Sub5Fix1" nver="1.5.1.250" req="false"></Book>
      </Book>
    </Book>
    <Book rev="20ver" nver="2.0.0.0">
      <Book rev="20Sub3" nver="2.3.0.1111">
        <Book rev="20Sub3Fix6" nver="2.3.6.1111" req="true"></Book>
        <Book rev="20Sub3Fix5" nver="2.3.5.1111" req="true"></Book>
        <Book rev="20Sub3Fix4" nver="2.3.4.1111" req="true"></Book>
        <Book rev="20Sub3Fix3" nver="2.3.3.1111" req="false"></Book>
        <Book rev="20Sub3Fix2" nver="2.3.2.1111" req="false"></Book>
        <Book rev="20Sub4" nver="2.4.0.1567">
          <Book rev="20Sub4Fix5" nver="2.4.5.1567" req="true"></Book>
          <Book rev="20Sub4Fix4" nver="2.4.4.1567" req="true"></Book>
          <Book rev="20Sub4Fix3" nver="2.4.3.1567" req="false"></Book>
          <Book rev="20Sub4Fix2" nver="2.4.2.1567" req="false"></Book>
          <Book rev="20Sub4Fix1" nver="2.4.1.1567" req="false"></Book>
        </Book>
      </Book>
    </Book>
  </Book>
</Books>

【讨论】:

    【解决方案2】:

    尝试例如$rslt = $parentXML.Node.InsertBefore($book, $parentXML.Node.SelectSingleNode(string.Format("Book[@req = '{0}']", $req)))。所以基本上为req值引入一个变量,如果存在则使用SelectSingleNode选择正确的兄弟并使用InsertBefore

    我不确定 Powershell 是否了解 C# string.Format,但我想你可以适应它 (System.String.Format?)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多