【问题标题】:Wrapping with Nokogiri用 Nokogiri 包裹
【发布时间】:2013-03-29 18:04:22
【问题描述】:

如果这个问题已经得到解答,我深表歉意,但我找不到正确的方法来解决这个问题。我正在使用 Nokogiri 修改通过应用程序生成的 SVG 图表,但遇到了一些问题。我正在使用的代码如下所示:

<svg>
    <g id="1">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
    <g id="2">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
    <g id="3">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
<svg>

我希望将其附加到脚本分析的每个文档中:

<svg>
  <g id="scale" transform="scale(1.0)">
    <g id="1">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
    <g id="2">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
    <g id="3">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
   </g>
<svg>

我尝试过使用 before 和 after 等方法,但在这种情况下无法正常工作。理想情况下,我只是用 wrap 包装整个节点集,但我不知道如何让它在所有集上工作,而不是在每个节点集上工作。任何指导将不胜感激。

谢谢!

【问题讨论】:

  • 看起来您的结束 svg 标记缺少斜杠。

标签: ruby svg nokogiri


【解决方案1】:

我会这样做:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<svg>
    <g id="1">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
    <g id="2">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
    <g id="3">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
</svg>
EOT

svg = doc.at('svg')
svg.children = '<g id="scale" transform="scale(1.0)">' + svg.children.to_xml + '</g>'
puts svg.to_xml

运行输出:

<svg>
  <g id="scale" transform="scale(1.0)">
    <g id="1">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
    <g id="2">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
    <g id="3">
        <text>lorem</text>
        <text>ipsum</text>
    </g>
</g>
</svg>

Nokogiri 很好地让我们将节点定义为字符串,并将它们强制为XML::Node 对象。给它一个包含 XML 的字符串,它会将其转换为 NodeSet,这样我们就可以干净利落地操作 XML DOM,而无需编写 u-gly 代码。

【讨论】:

    【解决方案2】:
    doc = Nokogiri.XML( raw_svg )
    wrapper_g = doc.create_element('g', 'id' => "scale", 'transform' => "scale(1.0)")
    doc.xpath('/svg/g').each {|elem| wrapper_g << elem }
    doc.root << wrapper_g
    

    可选 - 删除空文本节点:

    doc.xpath('//text()').each {|t| t.text =~ /\A\s*\z/ and t.remove }
    

    【讨论】:

      【解决方案3】:

      cheat sheet 可能会有所帮助。

      require 'nokogiri'
      
      doc = Nokogiri::XML(%Q{
      <svg>
          <g id="1">
              <text>lorem</text>
              <text>ipsum</text>
          </g>
          <g id="2">
              <text>lorem</text>
              <text>ipsum</text>
          </g>
          <g id="3">
              <text>lorem</text>
              <text>ipsum</text>
          </g>
      </svg>
      })
      
      svg = doc.xpath('//svg')[0]
      wrapper = doc.create_element('g', 'id' => 'scale', 'transform' => 'scale(1.0)')
      wrapper.children = svg.children
      svg.add_child wrapper
      
      puts doc
      

      请注意,您错过了结束 svg 标记处的斜线。

      【讨论】:

      • 不要使用doc.xpath('//svg')[0]。请改用at,这样更便于阅读(如果您想挑剔,请使用at_xpath)。
      • 感谢您的回复和链接。我肯定会参考这一点。
      猜你喜欢
      • 1970-01-01
      • 2014-07-30
      • 2014-05-03
      • 2014-02-12
      • 1970-01-01
      • 2018-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多