如何使用 Nokogiri 和 XPath 将元素添加到 XML

How to add an element to XML with Nokogiri and XPath

我有以下 XML:

    ?xml version="1.0" encoding="utf-8"?>
    <configuration>
  <!--
       The .NET 2.0 build of the console runner only 
    runs under .NET 2.0 or higher. The setting
    useLegacyV2RuntimeActivationPolicy only applies 
    under .NET 4.0 and permits use of mixed mode 
    assemblies, which would otherwise not load 
    correctly.
    -->
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <!-- Comment out the next line to force use of .NET 4.0 -->
  </startup>
  <runtime>
    <!-- Ensure that test exceptions don't crash NUnit -->
    <legacyUnhandledExceptionPolicy enabled="1"/>
    <!-- Run partial trust V2 assemblies in full trust under .NET 4.0 -->
    <loadFromRemoteSources enabled="true"/>
    <!-- Look for addins in the addins directory for now -->
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="lib;addins"/>
    </assemblyBinding>
  </runtime>
</configuration>

使用 Rakefile,我想在 <startup> 部分添加一个元素来表示:

<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />

成为:

<startup>
   <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>

目前我有这个:

task :update_test_runner_supported_runtime do
    test_runner_path   = 'Packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe.config'
    test_runner_config = Nokogiri::XML(open(functional_connection_path))
  functional_connection_config.xpath("//startup/")  #to find the start up element
  File.open(test_runner_path, 'w+') { |f| f.write(test_runner_config) } #to write the changes
end

为支持的 运行 时间添加此详细信息的实际语法是什么。

我想知道您是否可以通过简单的 sub! 调用来实现此目的?

test_runner_config.sub!('<startup useLegacyV2RuntimeActivationPolicy="true">', '<startup>\n    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />')
File.open(test_runner_path, 'w+') { |f| f.write(test_runner_config) }

试试这个。

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
  </startup>
  <runtime>
    <legacyUnhandledExceptionPolicy enabled="1"/>
    <loadFromRemoteSources enabled="true"/>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="lib;addins"/>
    </assemblyBinding>
  </runtime>
</configuration>

EOT

startup_node = doc.at('startup')
startup_node.delete('useLegacyV2RuntimeActivationPolicy')
startup_node.add_child('<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />')

at in doc.at('startup') tells Nokogiri to find the first <startup> node. delete is used to remove attributes of the node, and add_child 添加一个由字符串或另一个节点或节点集组成的子节点。

add_child 文档说:

Add node_or_tags as a child of this Node. node_or_tags can be a Nokogiri::XML::Node, a ::DocumentFragment, a ::NodeSet, or a string containing markup.

上面的代码导致:

doc.to_xml
# => "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
#    "<configuration>\n" +
#    "  <startup>\n" +
#    "  <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.7.2\"/></startup>\n" +
#    "  <runtime>\n" +
#    "    <legacyUnhandledExceptionPolicy enabled=\"1\"/>\n" +
#    "    <loadFromRemoteSources enabled=\"true\"/>\n" +
#    "    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\n" +
#    "      <probing privatePath=\"lib;addins\"/>\n" +
#    "    </assemblyBinding>\n" +
#    "  </runtime>\n" +
#    "</configuration>\n"