使用regex查找字符串,然后使用regex查找要替换的新字符串



我使用BatchGeo从电子表格创建地图,然后下载KML数据,这是:

<Placemark>
  <name>?</name>
    <Snippet></Snippet>
    <description><![CDATA[]]></description>
    <styleUrl>#style75</styleUrl>
    <address>1234 Example St Denver, CO 80221</address>
    <Point>
      <coordinates>-121.879364,37.815151,0.000000</coordinates>
    </Point>
</Placemark>

当导入谷歌地图时,这些点被放置在正确的地址/坐标上,但左侧栏每个引脚旁边的名称/描述符只显示"?"而不是显示地址。

我想使用正则表达式找到每个"<name>?</name>",然后使用正则表达式在文件中找到<address>.*</address>的NEXT实例,然后返回并将<name>标记之间的?替换为<address>标记之间的*

每个点的<Placemark>标签之间有一个代码块,总共有数百个点。

这是我目前收集到的一些信息:

newkml = File.open( 'Newkml.txt', 'w' )
def process_line(x)
  unless x == "<name>?</name>"
    # just return the original line
  else
    # Find the next instance of /<address>(.*)</address>/
    # Go to the original line
    # Replace it with "<name>#{$1}</name>"
  end
end
File.foreach('Whatever.kml'){|line|} do line.process_line
# Make a new file, copy over all of the lines that aren't <name>?</name>,
# and fix the name lines using the method above

UPDATE:在原始服务(BatchGeo)中,有一个选项可以设置哪些信息放在哪些KML(XML)标签中,因此我创建了一个新地图,并首先防止了问题的发生。感谢那些给我提供工具的人,我可以在将来使用这些工具进行这种手术。

更新2:尝试Mark Thomas的解决方案。下面是我运行的代码:

require 'rubygems'
require 'nokogiri'
doc = Nokogiri::XML("whatever.xml")
edits = 0
doc.xpath("//name").each do |name|
  if name.content == "?"
    name.content = name.xpath("following-sibling::address").text
    edits +=1
  end
end
puts( doc.inspect )
puts( "edits: #{edits}" )
puts doc

输出如下:

#<Nokogiri::XML::Document:0xfe0064 name="document>
edits: 0
<?xml version="1.0"?>

如果我添加的edits测试代码像我认为的那样工作,它似乎表明if name.content == "?"块执行了0次(比我预期的少130次)。

已经为您完成了用几乎任何语言解析/生成KML文件的工作。我想这个会适合你:https://github.com/schleyfox/ruby_kml

没有实际使用上面的库,我想确认我的建议-看起来所有的辅助函数都有创建KML文件,但仍然需要您使用XML解析器来加载一个。我仍然认为这比使用建议的XML解析器操作KML要好(尽管这当然也可以很好地工作),但是您可能还想看看http://georuby.rubyforge.org/georuby-doc/index.html,它确实支持KML输入和输出。

UPDATE 2 -为后代添加。

仔细考虑一下我的答案,我对这类问题的默认建议是:

  1. 解析KML为对象
  2. <
  3. 正确错误/gh>
  4. 重新生成KML

我的理由是应该不太容易破坏输出,如果你最终开始对KML做更多的操作,你已经完成了90%。

以上所述,在您的特定情况下,仅对已知数据进行更改,@Mark Thomas的方法将提供更快且代码开销更低的解决方案。

我建议使用XML解析器。这是一些示例Nokogiri代码:

doc = Nokogiri::XML(kml)
doc.xpath("//name").each do |name|
  if name.content == "?"
    name.content = name.xpath("following-sibling::address").text
  end
end

根据您的更新,似乎XML文件的解析出了问题——您确定它是有效的吗?

下面是一个完整的工作示例:

require 'nokogiri'
xml = <<End
<Placemark>
  <name>?</name>
    <Snippet></Snippet>
    <description><![CDATA[]]></description>
    <styleUrl>#style75</styleUrl>
    <address>1234 Example St Denver, CO 80221</address>
    <Point>
      <coordinates>-121.879364,37.815151,0.000000</coordinates>
    </Point>
</Placemark>
End
doc = Nokogiri::XML(xml)
doc.xpath("//name").each do |name|
  if name.content == "?"
    name.content = name.xpath("following-sibling::address").text
  end
end
puts doc
输出:

<?xml version="1.0"?>
<Placemark>
  <name>1234 Example St Denver, CO 80221</name>
    <Snippet/>
    <description/>
    <styleUrl>#style75</styleUrl>
    <address>1234 Example St Denver, CO 80221</address>
    <Point>
      <coordinates>-121.879364,37.815151,0.000000</coordinates>
    </Point>
</Placemark>

让我们试着用这个:

require 'nokogiri'
doc = Nokogiri::XML::DocumentFragment.parse(<<EOT)
<Placemark>
  <name>?</name>
  <Snippet></Snippet>
  <description><![CDATA[]]></description>
  <styleUrl>#style75</styleUrl>
  <address>1234 Example St Denver, CO 80221</address>
  <Point>
    <coordinates>-121.879364,37.815151,0.000000</coordinates>
  </Point>
</Placemark>
EOT
doc.search('Placemark').each do |placemark|
  name = placemark.at('name')
  address = placemark.at('address')
  name.content = address.text
end
puts doc.to_xml
输出:

<Placemark>
  <name>1234 Example St Denver, CO 80221</name>
  <Snippet/>
  <description><![CDATA[]]></description>
  <styleUrl>#style75</styleUrl>
  <address>1234 Example St Denver, CO 80221</address>
  <Point>
    <coordinates>-121.879364,37.815151,0.000000</coordinates>
  </Point>
</Placemark>

我使用文档片段来避免添加无关的内容。通常,您希望使用普通的Nokogiri::XML来解析文档。

我假设你有一个以上的<Placemark>标签,search将迭代,返回一个NodeSet。

相关内容

  • 没有找到相关文章

最新更新