2

在这个 XML 片段中,我需要为某些块替换 UID 中的数据。实际文件包含 100 多个类似的块。

尽管我已经能够基于name="Track (Timeline)"_ _<TrackID>name="Track (TimeLine)"<TrackID>0x1200UID

我是 Nokogiri 的新手,虽然我编写测试脚本,但我不认为自己是程序员。

<StructuralMetadata key="06.0E.2B.34.02.53.01.01.0D.01.01.01.01.01.3B.00" length="116" name="Track (TimeLine)">
    <EditRate>25/1</EditRate>
    <Origin>0</Origin>
    <Sequence>32-04-25-67-E7-A7-86-4A-9B-28-53-6F-66-74-65-6C</Sequence>
    <TrackID>0x1200</TrackID>
    <TrackName>Softel VBI Data</TrackName>
    <TrackNumber>0x17010101</TrackNumber>
    <UID>34-C1-B9-B9-5F-07-A4-4E-8F-F4-53-6F-66-74-65-6C</UID>
</StructuralMetadata>
<StructuralMetadata key="06.0E.2B.34.02.53.01.01.0D.01.01.01.01.01.3B.00" length="116" name="Track (TimeLine)">
    <EditRate>25/1</EditRate>
    <Origin>0</Origin>
    <Sequence>35-12-2D-86-E6-74-0B-4C-B4-24-53-6F-66-74-65-6C</Sequence>
    <TrackID>0x1300</TrackID>
    <TrackName>Softel VBI Data</TrackName>
    <TrackNumber>0x0</TrackNumber>
    <UID>37-0C-80-34-4C-8D-CE-41-85-F3-53-6F-66-74-65-6C</UID>
</StructuralMetadata>
4

2 回答 2

2

使用 xpath:

//StructuralMetadata

将选择StructuralMetadataXML 中的所有元素。开头的双斜线表示选择出现在文档中的任何节点。

虽然您不想要所有节点,但您可以使用谓词过滤您想要的节点:

//StructuralMetadata[@name="Track (TimeLine)" and TrackID="0x1200"]

这将选择具有value 属性的所有StructuralMetadata元素,以及具有 contents 的子元素。nameTrack (TimeLine)TrackID0x1200

当您对该UID元素感兴趣时,您可以进一步细化表达式:

//StructuralMetadata[@name="Track (TimeLine)" and TrackID="0x1200"]/UID

此表达式将匹配作为与上述谓词匹配的UID元素的子元素的所有元素。StructuralMetadata

使用它:

require 'nokogiri'

# Parse the document, assuming xml_file is a File object containing the XML
doc = Nokogiri::XML(xml_file)

# I'm assuming there is only one element in the document that matches
# the criteria, so I'm using at_xpath
node = doc.at_xpath('//StructuralMetadata[@name="Track (TimeLine)" and TrackID="0x1200"]/UID')

# At this point, doc contains a representation of the xml, and node points to
# the UID node within that representation. We can update the contents of
# this node
node.content = 'XXX'

# Now write out the updated XML. This just writes it to standard output,
# you could write it to a file or elsewhere if needed
puts doc.to_xml
于 2012-04-04T19:19:38.883 回答
1

解决这个问题的一个好方法是使用“map reduce”编程风格,它可以获取大量事物并将其缩小并将其组合成您所追求的结果。具体来说,Array#find对于Array#select这类问题非常有用。看看这个例子:

require 'nokogiri'
xml = Nokogiri::XML.parse(File.read "sample.xml")
element = xml.css('StructuralMetadata').find { |item|
  item['name'] == "Track (TimeLine)" and item.css('TrackID').text == "0x1200"
}
puts element.to_xml

这个小程序首先使用 CSS 选择器来获取<StructuralMetadata>文档中的所有元素。Array#find它返回一个数组,我们可以使用该方法过滤出我们想要的内容。Array#select是它的表亲,它返回一个包含所有匹配对象的数组,而不是它碰巧找到的第一个。

在块内,我们有一个测试来检查<StructuralMetadata>标签是否是我们所追求的。然后它把element.to_xml字符串放到控制台,这样如果你把它作为命令行脚本运行,你就可以看到它找到了什么。现在您可以找到该元素,您可以以通常的方式对其进行修改并保存一个新的 XML 文件或其他任何内容。

于 2012-04-04T11:06:02.350 回答