5

このファイルhttp://techpatterns.com/downloads/firefox/useragentswitcher.xml から txt ファイルにブラウザーを一覧表示し、%tab% 区切り記号で区切るのを手伝ってくれません か?

3 つまたは 4 つの列があるはずです。

1) サンプルデータからのフォルダの説明: <folder description="Browsers - Windows">

2) サンプルデータからのブラウザタイプ:<folder description="Legacy Browsers">

3) サンプルデータからのユーザーエージェント:<useragent description="Avant Browser 1.2" useragent="Avant Browser/1.2.789rel1 (http://www.avantbrowser.com)" app

ここで、一部のブラウザーはフォルダーでは<folder description="Legacy Browsers">"なく、下にあるため、最初の問題が表示されます<separator/>

したがって、1 列目はシステムを定義し、2 列目はタイプ、3 列目はブラウザーを定義する必要があります。

次の問題は、Devises フォルダーにもう 1 つのフォルダーが含まれていることです。

@echo off 
Setlocal EnableDelayedExpansion
SET file=useragentswitcher.xml
SET delim="

FOR /F "tokens=* skip=1" %%F IN (!file!) DO (
  REM echo %%F
  call :parse "%%F" > temp.txt
  FOR /F "tokens=1,2,3,4,5,6,7 skip=1 delims=" %%A IN (temp.txt) DO (
    IF "%%A"=="folder" (
      SET /A level=!level!+1
      echo Level:!level!
      ) ELSE IF "%%A"=="/folder" (
          SET /A level=!level!-1
          echo Level:!level!
        )

   echo A:%%A
  )
  pause
)

exit /b

:parse
Setlocal EnableDelayedExpansion
  SET A=%*
  REM REMOVE double paranthesis and <> 
  SET A=!A:~2,-2!
  REM replace double qoutes
  SET A=!A:"=µ!
  FOR /F "tokens=1,2 delims=µ=" %%A IN ("!A!") DO (
    SET first=%%A
    SET second=%%B
    echo !first!
    FOR /F "tokens=1,2 delims= " %%A IN ("!first!") DO (
      echo %%A
      echo %%B
    )
    echo !second!
  )
endlocal
exit /b

これにより、行の 1 つのタグが解析されます。これから作業を進めます。

4

3 に答える 3

6

XML を解析するには、バッチよりもはるかに優れたツールを見つけることができるはずです...

しかし、以下のコードはあなたが探しているものだと思います。

フォルダーの数が異なるため、出力の列の順序を入れ替えました。ブラウザーの説明を最初に配置し、その後にフォルダーを 1 列に 1 つずつ配置します。これにより、各列の定義を固定できます。

jebの回答の情報を使用し"て、FOR区切り文字として含めました。

編集 - コードを簡略化しました

注 - この最初の試行は、Internet Explorer を使用して取得された XML のコピーで機能するように記述されています。その後、IE がファイルの形式を変更したことを発見しました。このコードはファイルの正確な形式に大きく依存するため、元の XML では機能しません。また、バッチが XML の解析に適していない理由の例としても役立ちます。

@echo off
setlocal enableDelayedExpansion

::Define the files to use - change as needed
set input="test.xml"
set output="result.txt"

::The assignment below should have exactly one TAB character between = and "
set "TAB=   "

set cnt=0
set "folder0="
>%output% (
  for /f usebackq^ tokens^=1^,2^ delims^=^=^" %%A in (%input%) do (
    for %%N in (!cnt!) do (
      if "%%A"=="- <folder description" (
        set /a cnt+=1
        for %%M in (!cnt!) do set "folder%%M=!folder%%N!%TAB%%%B"
      )
      if "%%A"=="  </folder>" (
        set /a cnt-=1
      )
      if "%%A"=="  <useragent description" (
        echo %%B!folder%%N!
      )
    )
  )
)

!展開が遅れると、!. 確認しましたが、あなたのファイルには!説明がありません。

説明で処理するようにコードを変更することもできますが!、より複雑になります。遅延拡張のオンとオフの切り替え、および ENDLOCAL バリアを越えた変数値の保存が必要です。

上記のコードは、XML の形式に大きく依存しています。非標準のダッシュが削除された場合、または空白の配置が変更された場合は失敗します。

次のバリエーションはもう少し堅牢ですが、各行に XML タグが 1 つだけ含まれている必要があります。

@echo off
setlocal enableDelayedExpansion

::Define the files to use - change as needed
set input="test.xml"
set output="result.txt"

::The assignment below should have exactly one TAB character between = and "
set "TAB=   "

set cnt=0
set "folder0="
>%output% (
  for /f usebackq^ tokens^=1^,2^ delims^=^=^" %%A in (%input%) do (
    for %%N in (!cnt!) do (
      set "test=%%A"
      if "!test:<folder description=!" neq "!test!" (
        set /a cnt+=1
        for %%M in (!cnt!) do set "folder%%M=!folder%%N!%TAB%%%B"
      )
      if "!test:</folder>=!" neq "!test!" (
        set /a cnt-=1
      )
      if "!test:<useragent description=!" neq "!test!" (
        echo %%B!folder%%N!
      )
    )
  )
)

編集 - 最後のバージョン

!こちらはデータで扱えるバージョンです。出力に列を追加しました。最初の列は依然としてブラウザの説明です。2 列目はユーザーエージェント文字列です。残りの列はフォルダーです。このソリューションでは、遅延拡張トグル手法を使用します。また、追加の FOR /F を使用して、ENDLOCAL バリアを越えて変数値を保持します。

@echo off
setlocal disableDelayedExpansion

::Define the files to use - change as needed
set input="test.xml"
set output="result.txt"

::The assignment below should have exactly one TAB character between = and "
set "TAB=   "

set cnt=0
set folder0=""
>%output% (
  for /f usebackq^ tokens^=1-4^ delims^=^=^" %%A in (%input%) do (
    set "test=%%A"
    set "desc=%%B"
    set "agent=%%D"
    setlocal enableDelayedExpansion
    for %%N in (!cnt!) do (
      if "!test:<folder description=!" neq "!test!" (
        set /a cnt+=1
        for %%M in (!cnt!) do for /f "delims=" %%E in ("!folder%%N!") do (
          endlocal
          set "folder%%M=%%~E%TAB%%%B"
          set "cnt=%%M"
        )
      ) else if "!test:</folder>=!" neq "!test!" (
        endlocal
        set /a cnt-=1
      ) else if "!test:<useragent description=!" neq "!test!" (
        echo !desc!%TAB%!agent!!folder%%N!
        endlocal
      ) else endlocal
    )
  )
)
于 2012-06-13T16:06:50.817 に答える
1

あなたのコメントに答えるHow should I use double quotes as delimiter?

フォームを使用するだけです

FOR /F tokens^=1^,2^ delims^=^" %%B IN ("%%A") DO

これはどのように機能しますか?
通常、引用文字をデリム文字として使用することはできません。
これが唯一の既知の回避策です。重要なことは、FOR/Fオプションを囲む通常の引用符が欠落していることです。
ただし、オプションは1つのトークンとしてのみ解析される必要があるため、すべての標準のバッチパーサー区切り文字(スペースタブ= 、;)をエスケープする必要があります。
引用符はバッチ区切り文字ではありませんが、行の残りの部分が引用符で囲まれるのを避けるために、それもエスケープする必要があります。そうしないと、パーサーは失敗します。ただし、2番目の引用符は無視されるため、 withを
変更できます。^"""

FOR /F tokens^=1^,2^ delims^="" %%B IN ("%%A") DO ...
于 2012-06-13T13:47:53.410 に答える