2014-06-15 42 views
0

我有一堆包含地理空間信息的大型XML文檔(KML,如果有人有興趣),其排列方式如下:顯示XML元素值,如果字符的次數超過規定的閾

<Placemark><SimpleData name="species">Unique number</SimpleData> ... coordinates</Placemark> 

我希望列出所有物種ID,其中地標標籤之間的總字符數超過給定閾值 - 1,000,000。以下AWK腳本指示哪些行突破限制:

for kmlfile in *.kml; do 
    echo "Processing $kmlfile" 
    awk -- '/<Placemark>/,/<\/Placemark>/ { if (length() > 10000) { printf("Line %d has %d characters\n", NR, length()); } }' $kmlfile 
done 

但我不知道如何讓它顯示物種ID而不是行號。任何想法如何使它AWK,Python或任何你喜歡的東西?

這裏是一個片段文檔的樣子:

<Document xmlns="http://www.opengis.net/kml/2.2"> 
    <Folder><name>Export_Output02</name> 
     <Placemark> 
      <Style><LineStyle><color>ff0000ff</color></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style> 
      <ExtendedData><SchemaData schemaUrl="#Export_Output02"> 
       <SimpleData name="species">1312</SimpleData> 
       <SimpleData name="area">7848012</SimpleData> 
       <SimpleData name="irrep_area">0.00000012742</SimpleData> 
       <SimpleData name="groupID">2</SimpleData> 
      </SchemaData></ExtendedData> 
      <MultiGeometry> 
       <Polygon> 
        <outerBoundaryIs> 
         <LinearRing> 
          <coordinates>-57.843052746056827,-33.032934004012787 -57.825312079170494,-33.089724736921667 -57.888494029914156,-33.073777852969904 -57.843052746056827,-33.032934004012787</coordinates> 
         </LinearRing> 
        </outerBoundaryIs> 
       </Polygon> 
       <Polygon> 
        <outerBoundaryIs> 
         <LinearRing> 
          <coordinates>-57.635769389832561,-33.032934004012787 -57.618028722946228,-33.089724736921667 -57.681210673689904,-33.073777852969904 -57.635769389832561,-33.032934004012787</coordinates> 
         </LinearRing> 
        </outerBoundaryIs> 
       </Polygon> 
      </MultiGeometry> 
     </Placemark> 
    </Folder> 
</Document> 

而且整個文件的例子:link to GDrive

[編輯] 我應該補充一點,Google地圖融合表對「地標」中的字符數進行限制。每個地標都描述了地圖上的特定功能,並且地圖上可能有許多這樣的功能。如果任何地標中斷了1M個字符限制,則轉換爲融合表將失敗。

+1

爲什麼你要計算字符,當你的數據是XML?任意字符是否以任何方式相關?例如,你不能使用XML提取和測試元素的內容嗎?使用XML方法可以很容易地計算某個元素中的字符數。在實際選擇多個文件的情況下,爲什麼不測試文件大小? (在我看來,10000和「」之外的幾個字符之間的差別非常小,並且是無關緊要的。)也許你應該描述你正在努力達到的目標。 – helderdarocha

+0

謝謝@helderdarocha再次查看我的問題。 Google融合表格不接受超過一百萬個字符的「地標」。出於這個原因,我需要找到超出此限制的所有地標,並對它們執行一些手動預處理。由於我有6000個文件,我不想一個接一個地檢查哪個'物品'違反了限制。我如何提取「地標」?我嘗試了下面這些例子[link](http://stackoverflow.com/questions/10475654/extract-elements-from-xml-file-using-python),但我總是得到一個空的列表。 –

回答

0

我想出了一個粗略的Python腳本來完成這項工作。當然,這不是最好的方法,所以如果你有更好的方法,我會很高興看到它。此外,我提取物種ID的方式相當難看 - 建議熱點使它更漂亮也受到歡迎。

import glob 
from collections import namedtuple 
Placemark = namedtuple('Placemark', 'found no_characters specie_id end_idx') 


def GetPlacemark(input_file, start): 
    start_idx = input_file.find('Placemark', start) 
    end_idx = input_file.find('/Placemark', start) 
    if start_idx == -1 or end_idx == -1: 
     return Placemark(False, -1, -1, -1) 
    no_characters = end_idx - start_idx 
    specie_name_idx = input_file.find('species', start_idx, end_idx) 
    specie_id_start_idx = input_file.find('>', specie_name_idx) 
    specie_id_end_idx = input_file.find('<', specie_name_idx) 
    specie_id = int(data[specie_id_start_idx+1:specie_id_end_idx]) 
    return Placemark(True, no_characters, specie_id, end_idx) 

path_to_kml = glob.glob('*.kml') 
for kml_file in path_to_kml: 
    print 'Processing ' + kml_file 
    with open (kml_file, "r") as myfile: 
     data=myfile.read().replace('\n', '') 

    placemarks = [] 
    current_idx = 0 

    while True: 
     mark = GetPlacemark(data, current_idx) 
     if mark.found: 
      placemarks.append(mark) 
      current_idx = mark.end_idx + 1 
     else: 
      break 

    for placemark in placemarks: 
     if placemark.no_characters > 1000000: 
      print 'Specie %d has %d characters' % (placemark.specie_id, placemark.no_characters) 
    print 'Done\n' 
相關問題