2012-04-07 241 views
0

我有這個腳本來讀取xml文件。該文件包含座標和我想列出的座標:從xml文件讀取座標

@echo off 
setlocal EnableDelayedExpansion 

FOR %%K IN (*.xml) DO (
SET K=%%K 
SET K=!K:~0,-4! 
SET "prep=0" 

    REM READ DATA 
    FOR /F "tokens=*" %%X IN (!K!.kml) DO (
    if !prep! == 1 (
    echo %%X 
    pause 
     FOR /F %%L IN ("%%X") DO (
     SET L=%%L 
     IF NOT "!L:~0,1!" == "<" (
     echo %%L 
     )  
    ) 
     SET "prep=0" 
    ) 
    if "%%X" == "<coordinates>" (SET "prep=1") 
    ) 
) 

我得到這些結果:

14.63778004128814,49.50141683426452,0 14.63696238385996,49.48348965654706,0 14.6 
8840586504191,49.47901033971912,0 14.68589371304878,49.49939179836829,0 14.63778 
004128814,49.50141683426452,0 </coordinates> 
Press and key to continue... 
14.63778004128814,49.50141683426452,0 
Press and key to continue... 

首先,你看到的座標系。其次,在第三個循環中,打印座標。但是我只打印了一對座標......如果再次按下某個鍵,則批次將不打印下一列。你能幫我嗎?

編輯 答案已經發布後,我有問題1)我們可以利用這一點:

SET LF=^ 


setlocal EnableDelayedExpansion 
... (next code) ... 
set "var=!var: =%LF%!"  

因此,當不存在延遲LF變量,我們可以將其嵌入。或不?

; 2)爲什麼在你的代碼

for %%L in ("!LF!") do set "X=!X: =%%~L!" 

你使用%%〜L和不只是%%大號

回答

1

你眼前的問題是,FOR/F不重複的令牌線。它只是解析你所要求的每個標記。如果你沒有指定「標記」選項,那麼它默認爲「標記= 1」 - 它只解析行中的第一個標記。

但是,如果字符串包含換行符,FOR/F會將字符串視爲多行。然後它會像你想要的那樣遍歷每一行。訣竅是用換行符替換空格分隔符。有多種方法可以完成這項工作,但是我會展示我認爲最簡單的工作方式。

首先定義一個包含一個換行符

set LF=^ 


::The two blank lines above are critical for the definition of the line feed 

接下來的關鍵是要替換空格與換行符您的變量的變量。正常情況下替代使用變量將看起來像set "var=!var:search=%replaceVar%!"。但是這對LF變量不起作用 - 使用正常擴展很難處理LF變量。使用延遲擴展要容易得多。我們不能在延遲擴展中嵌入延遲擴展,但是我們可以將LF的值傳遞給一個簡單的FOR變量,並使用for %%L in ("!LF!") do set "var=!var: =%%~L!"

有關代碼的一件事我不明白 - 您的初始FOR循環遍歷所有.KML文件。您使用子字符串操作剝離擴展名。沒有使用環境變量,有一種更簡單的方法:%%~nK將給出沒有擴展名的文件的基本名稱。但是,當你轉過身來再次追加擴展名時,爲什麼會這樣呢?

我直接使用了%% K值 - 我添加了USEBACKQ選項並添加了引號以允許在文件名中使用空格。

這裏是代碼,應該做你所期待的。

@echo off 
setlocal EnableDelayedExpansion 

::define a variable containing a linefeed character 
set LF=^ 


::Above 2 blank lines are part of the LF definition, do not remove 

for %%K in (*.kml) do (
    set "prep=0" 
    for /f "usebackq tokens=*" %%X in ("%%K") do (
    if !prep! == 1 (
     echo %%X 
     pause 
     set "ln=%%X" 
     for %%L in ("!LF!") do set "ln=!ln: =%%~L!" 
     for /f %%L in ("!ln!") do (
     set L=%%L 
     if not "!L:~0,1!" == "<" (
      echo %%L 
     ) 
    ) 
     set "prep=0" 
    ) 
    if "%%X" == "<coordinates>" (set "prep=1") 
) 
) 

但我覺得你有更大的問題。我擔心你正在使用批處理解析XML來爲自己的世界設置痛苦。您假設XML將始終以相同的方式佈局。有無數有效的方法在XML文檔中添加或減去換行符和空白區域,這會破壞您的算法。你能確定你的所有輸入文件都來自同一個源文件,並且總是會像你期望的那樣格式化嗎?我認爲你真的應該使用XSLT來解析和轉換你的XML文檔到一個裸體的座標列表中。

Answsers更多的問題

1)set "var=!var: =%LF%!"將無法​​正常工作 - LF定期擴展需要轉義序列和多個擴展。這將工作:set "var=!var: =^%LF%LF%!"

%LF%的轉義序列可以變得非常棘手,所以我儘量避免它們。

2)關於for %%L in ("!LF!") do set "X=!X: =%%~L!",請注意它是一個簡單的FOR,而不是FOR/F。 !LF!必須被引用,否則FOR將不會讀取它。但FOR語句保留了引號(與FOR/F不同),所以我需要%%〜L來刪除封閉的引號。

FOR和FOR/F在換行符之間有一個非常重要的區別。 FOR將保留帶引號的換行符,而FOR/F將換行符視爲行分隔符並對每行進行迭代,因此不會保留換行符。

+0

謝謝。這是一個很長的回答(替代解決方案非常簡單)。我會多次評論這個。現在只需註釋xml解析。不,我不打算創建XML解析器。我只需要這一個信息。這個xml是由程序生成的,並且應該始終是相同的。 – user1141649 2012-04-07 14:35:14

+0

我刪除擴展名的原因是我在此代碼後創建了文件夾。另外我會將座標以行格式寫入名爲temp /!K!.txt的文件 – user1141649 2012-04-07 15:01:56

+0

爲什麼我不能添加如下所示的引號: SET「LF = ^」(換行符在這裏出現) – user1141649 2012-04-07 15:12:52