从xml文件中读取坐标

时间:2012-04-07 10:36:56

标签: batch-file readfile

我有这个脚本,要读取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...

首先,您会看到带坐标的线条。其次,在第3个循环中,打印了坐标。但是我只打印了一对坐标...如果我再次按一个键,批处理完成而不打印下一列。你能帮忙吗?

修改 答案发布后,我有问题1)我们可以使用这个:

SET LF=^


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

因此,当没有延迟的LF变量时,我们可以嵌入它。或者不是?

和2)为什么在你的代码中

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

你使用%% ~L而不仅仅是%% L

1 个答案:

答案 0 :(得分:1)

您当前的问题是FOR / F不会在一行中迭代令牌。它只是解析您要求的每个令牌。如果你没有指定“标记”选项,那么它默认为“tokens = 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文档解析并转换为裸露的坐标列表。

回答其他问题

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将换行符视为行分隔符并迭代每一行,因此不会保留换行符。

相关问题