2011-03-18 12 views
1

我有良好的xml(開放標籤已關閉等),但沒有dtd,命名空間並不總是正確的,並且存在隨機實體。操作格式良好的XML(在linux下運行的任何語言)

我在一些xml文件中發現了錯誤,並且想自動修復此錯誤。本質上,XML文件看起來像這樣:

<foo> 
    <bar>  hi </bar> 
    <!-- ... --> 
    <math><sometag><another>bar</another></sometag></math> 
    <!-- ... --> 
</foo> 

我想改變這

<foo> 
    <bar>  hi </bar> 
    <!-- ... --> 
    <m:math><m:sometag><m:another>bar</m:another></m:sometag></m:math> 
    <!-- ... --> 
</foo> 

我看着Python的ElementTree的,但根據diveintopython的也不會喜歡這樣的事實,它不驗證XML ?另外,除了使用m:的前綴之外,不應該更改任何內容。

由於我正在寫一堆shell腳本來修復文件,我並不真正關心這門語言,儘管我目前選擇的武器是Python。

澄清:

  • 的XML並通過在其上執行xmllint
  • 我真的想要一個XML解決方案,因爲解析使用正則表達式XML的方式古怪
  • 我不知道可以在<math></math>之間的標籤的名稱
  • 不應修改文檔,但 th前綴標記的前綴m:
+0

+1「使用正則表達式解析xml是w ay to flakey「 – 2011-03-19 00:41:11

+0

最後,我結束了匹配 ...與正則表達式(因爲然後我可以使用這個替換在xml不保證驗證過程中的一個點):http:// stackoverflow .com/questions/5409161/how-to-prevent-elementtree-fromstring-or-tostring-from-dropping-commentnode。我第一次嘗試使用Beautifulsoup,但是對於xml,這似乎更安全,並且它是空間保留的,但只是失去了評論。感謝大家!我學到了很多:) – markijbema 2011-03-23 17:21:40

回答

2

在Ruby中,使用引入nokogiri按摩XML:

xml = <<EOT 
<foo> 
    <bar>  hi </bar> 
    <!-- ... --> 
    <math><sometag><another>bar</another></sometag></math> 
    <!-- ... --> 
</foo> 
EOT 

NAMESPACE = %w[m http://host.com/m] 

require 'nokogiri' 
doc = Nokogiri::XML::DocumentFragment.parse(xml) 

ns = doc.at('foo').add_namespace_definition(*NAMESPACE) 

doc.xpath('foo/math | foo/math//*').each { |n| n.namespace = ns } 

puts doc.to_xml 

輸出看起來像:

>> <foo xmlns:m="http://host.com/m"> 
>> <bar>  hi </bar> 
>> <!-- ... --> 
>> <m:math><m:sometag><m:another>bar</m:another></m:sometag></m:math> 
>> <!-- ... --> 
>> </foo> 

如果命名空間不能被添加到<foo>,那麼你可以Munge時間標籤名稱直接與名稱空間無關:

xml = <<EOT 
<foo> 
    <bar>  hi </bar> 
    <!-- ... --> 
    <math><sometag><another>bar</another></sometag></math> 
    <!-- ... --> 
</foo> 
EOT 

NAMESPACE = %w[m http://host.com/m] 

require 'nokogiri' 
doc = Nokogiri::XML::DocumentFragment.parse(xml) 

doc.xpath('foo/math | foo/math//*').each { |n| n.name = "m:" << n.name } 

puts doc.to_xml 

# >> <foo> 
# >> <bar>  hi </bar> 
# >> <!-- ... --> 
# >> <m:math><m:sometag><m:another>bar</m:another></m:sometag></m:math> 
# >> <!-- ... --> 
# >> </foo> 
4

Perl中的單行表示ok嗎?

$ perl -lne'm!<math>.*</math>! and s!<(/)?([^>]+)>!<$1m:$2>!gm;print' 5351382.txt 
<foo> 
    <bar>  hi </bar> 
    <!-- ... --> 
    <m:math><m:sometag><m:another>bar</m:another></m:sometag></m:math> 
    <!-- ... --> 
</foo> 

你真的不應該解析XML這種方式...但如果上面是夠你...;)

+0

嘿,我總是欣賞一個很好的oneliner;)但是我寧願使用XML解析方法,因爲我知道標籤要保持良好平衡,所以這樣(我用xmllint來檢查xml是平衡好)。這樣的文本操作方法很棘手,例如,您的解決方案用''替代''。所以我寧願使用xml庫解決方案。 – markijbema 2011-03-18 12:28:48

+0

我真的很喜歡這個'm!和s !!!'建設。你能解釋一下這是如何工作的,或者指出一個解釋它的網站?我已經做了很多perl,但不知道這個構造。 – markijbema 2011-03-18 13:29:44

+0

您不必在Perl中使用/作爲正則表達式分隔符,您可以使用任何單個字符或平衡對:s#foo#bar#或s {foo} {bar}或甚至s正則表達式引擎平衡了括號,所以外括號分隔了正則表達式,而內括號是模式的一部分) – mirod 2011-03-18 13:50:30

1

你最好的選擇可能是要找到一個非驗證XSLT處理器並通過它像: <xsl:template match="math"> <m:math> <xsl:apply-templates select="@*|node()"/> </m:math> </xsl:template>

+0

但是,這不會添加'm:'前綴標籤內的標籤,對嗎?我不知道在''和''之間可能出現的標籤名稱。 – markijbema 2011-03-18 13:23:52

+0

呃,是的,這正是它的作用。並且它們內部的內容並不重要,這由'select =「@ * | node()」'子句處理。 – TMN 2011-03-18 13:29:51

6

在Perl中你可以使用XML::Twig,例如像這樣:

#!/usr/bin/perl 

use strict; 
use warnings; 

use XML::Twig; 

XML::Twig->new(twig_roots => { math => \&add_prefix }, 
       twig_print_outside_roots => 1, 
      ) 
     ->parse(\*DATA); 

sub add_prefix 
    { my($t, $math)= @_; 
    foreach my $m ($math, $math->descendants('#ELT')) 
     { $m->set_tag("m:" . $m->tag); } 
    $t->flush; 
    } 

__DATA__ 
<foo> 
    <bar>  hi </bar> 
    <!-- ... --> 
    <math><sometag><another>bar</another></sometag></math> 
    <!-- ... --> 
</foo> 
1

也許BeautifulSoup將比Python內置的東西更好地爲您服務。它主要設計用於HTML,但可以做的XML爲好,雖然......

的BeautifulSoup類是全網頁瀏覽器般的啓發式方法佔卜HTML作者的意圖。但是XML沒有固定的標籤集,所以這些啓發式不適用。所以BeautifulSoup不會很好地執行XML。

它可能不是完美的,但可能比未嚴格解析器的未指定或無效XML更好。有利於它的另一點是它gives you Unicode, dammit

+0

但它保留原始佈局與間距等?我處在一個管道中間,並且對這個文件發生的事情沒有太多控制,也不知道到底發生了什麼。因此,我需要在安全方面犯錯,只使用不會改變空格/註釋/縮進或任何操作的操作。 – markijbema 2011-03-18 16:04:00

+0

不,我認爲它不會做任何保留空白的嘗試......對不起。 – Thomas 2011-03-18 16:13:43

+0

「美化方法增加了戰略換行和間距,使文檔的結構變得明顯,它還去除了只包含空格的文本節點,這可能會改變XML文檔的含義。str和unicode函數不會去掉只包含空格的文本節點,並且它們不會在節點之間添加任何空格。「所以我認爲它的確如此,大多數情況下,如果你只是使用'str(soup)'。 – markijbema 2011-03-23 17:01:04

相關問題