2013-01-17 86 views
1

我用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> 

当导入到Google地图中后,这些点将放置在正确的地址/坐标处,但左侧边栏上每个引脚旁边的名称/描述符只会显示“?”而不是显示地址。

我想用一个正则表达式找到每个"<name>?</name>",然后使用正则表达式查找的文件中<address>.*</address>下一个实例,然后回去与*那是<address>标签之间更换<name>标签之间的?

每个点的<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次)。

+7

[Nokogiri](http://nokogiri.org/)。 – harbichidian

+2

使用XML解析器来处理XML,就像echoback所建议的一样。 – nhahtdh

+1

谢谢,我不知道这样的事情存在。现在阅读文档 - 看起来Nokogiri会有解决方案。我会在这里更新,如果我找到一个。 –

回答

2

我推荐使用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> 
+0

我试着运行这个,它没有错误地执行,但在文档中似乎没有改变。然后,我按照以下方式对其进行了修改,以查看代码块是否正在运行: –

+0

您是否输出了新的文档?尝试'放入doc'。 –

+0

请参阅上面的更新,显示我运行的代码和结果。 –

3

的工作已经为你做了解析/生成几乎任何语言的KML文件。我怀疑这人会为你工作:https://github.com/schleyfox/ruby_kml

UPDATE

有没有实际使用,我想确认一下我的建议上述库 - 看起来像所有的辅助功能是否有用于创建KML文件,但会仍然要求您使用XML解析器来加载一个。我仍然认为这比使用XML解析器处理你的KML更好(尽管这肯定也能正常工作),但你也可以看看支持KML输入和输出的http://georuby.rubyforge.org/georuby-doc/index.html

UPDATE 2 - 为后代添加。

把一些更多的思考进入我的回答,我对这样的问题,默认的建议是:

  1. 的KML解析为对象
  2. 纠正错误
  3. 重新生成KML

我的推理是这样的应该不容易打乱输出,如果你最终开始做更多的KML操纵你ar那里已经有90%的路了。

这就是说,在您的具体情况下,您只需对已知数据进行更改,@Mark Thomas的方法将提供更快,更低代码开销的解决方案。

+0

尽管我大体上同意KML解析器/生成器比用XML解析器手动生成KML解析器/生成器要好,但我不确定KML解析器能否解决手头的数据质量问题。 –

+0

我的方法是使用georuby库将KML解析为对象,迭代列表以更正数据问题,然后输出结果。这就是说,按照你的规划,这是一个非常简单的XPath解决方案,这可能是矫枉过正的,直到你需要或想要进行其他更改(也许应用条件式等) – Matthew

0

让我们尝试使用此:

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。

相关问题