Xml 在定义的字符串后查找特定字符串
我正在尝试基于.xml文件为已安装的库生成.txt报告。 它应该报告库SNPID号|库名称|注册表项|库路径。按升序编号排序,最后对齐列 主要问题是,当.xml文件只有一个SNPID和一个名称时,脚本可以工作,但当.xml包含多个SNPID和名称时,脚本不能工作 一些提示: .xml文件中搜索的字符串/行始终具有附加空格 SNPID也可以有字母。 在里面我们可以有多个 在里面我们可以有多个 顺序始终相同,名称为1: 但是Name/SNPID可以在内部,也可以在内部 当里面有价值时,所有口味的产品注册码都是一样的。 这是我到目前为止的代码Xml 在定义的字符串后查找特定字符串,xml,powershell,batch-file,Xml,Powershell,Batch File,我正在尝试基于.xml文件为已安装的库生成.txt报告。 它应该报告库SNPID号|库名称|注册表项|库路径。按升序编号排序,最后对齐列 主要问题是,当.xml文件只有一个SNPID和一个名称时,脚本可以工作,但当.xml包含多个SNPID和名称时,脚本不能工作 一些提示: .xml文件中搜索的字符串/行始终具有附加空格 SNPID也可以有字母。 在里面我们可以有多个 在里面我们可以有多个 顺序始终相同,名称为1: 但是Name/SNPID可以在内部,也可以在内部 当里面有价值时,所有口味的产品
@echo off
pushd "%~dp0"
setlocal
set "Backup_Folder=%~dp0NI_Backup"
set "SNPID_List=%Backup_Folder%\SNPID_Report.txt"
set "SNPID_TMP_List_To_Order=%Backup_Folder%\SNPID_TMP_List_To_Order.txt"
set "SNPID_TMP_List_To_Realign=%Backup_Folder%\SNPID_TMP_List_To_Realign.txt"
set "XML_Dir=C:\Program Files\Common Files\Native Instruments\Service Center"
set "Registry_Key=HKLM\SOFTWARE\Native Instruments"
if not exist "%Backup_Folder%" ( mkdir "%Backup_Folder%" >nul 2>&1 )
setlocal EnableDelayedExpansion
REM Loop through .xml
(
for /f "delims=" %%a in ('dir /s/b/a-d "%XML_Dir%\*.xml"^| find /v "NativeAccess" ^| find /v "ProductHints" ^| find /v "Maschine 2"') do (
for /f "usebackqtokens=1-3delims=<>" %%E in ("%%a") do (
if "%%F"=="SNPID" (
for /f "usebackqtokens=1-3delims=<>" %%I in ("%%a") do (
if "%%J"=="Name" (
for /f "usebackqtokens=1-3delims=<>" %%M in ("%%a") do (
if "%%N"=="RegKey" (
for /f "tokens=2*" %%Q in ('reg query "%Registry_Key%\%%O" /v "ContentDir" 2^>nul ') do (
set "ContentDir=%%R"
if "!ContentDir:~1,2!"==":\" ( echo %%G ^| %%K ^| %Registry_Key%\%%O ^| %%R )
))))))))
)>"%SNPID_TMP_List_To_Order%"
REM Rename Paths ending with backslash
call "%~dp0Jrepl.bat" "(.*)\\$" "$1" /xseq /m /f "%SNPID_TMP_List_To_Order%" /o -
REM Remove duplicates
call "%~dp0Jrepl.bat" "\c([\c\r\n]+)\r?\n(?=[\s\S]*\c\1$)" "" /xseq /m /f "%SNPID_TMP_List_To_Order%" /o -
REM echo column title
echo SNPID^| Library Name^| Registry Key^| Library Location>"%SNPID_TMP_List_To_Realign%"
REM Sort by SNPID number
sort <"%SNPID_TMP_List_To_Order%" >>"%SNPID_TMP_List_To_Realign%"
REM Get Columns length
set "SNPID_MaxLength=0"
set "LibName_MaxLength=0"
set "RegKey_MaxLength=0"
for /f "usebackqtokens=1-3 delims=|" %%a in ("%SNPID_TMP_List_To_Realign%") do (
set "String=%%a" & call :strlen
for /f "tokens=* delims=0" %%B in ("!result!") do (
if %%B gtr !SNPID_MaxLength! set "SNPID_MaxLength=%%B"
)
set "String=%%b" & call :strlen
for /f "tokens=* delims=0" %%B in ("!result!") do (
if %%B gtr !LibName_MaxLength! set "LibName_MaxLength=%%B"
)
set "String=%%c" & call :strlen
for /f "tokens=* delims=0" %%B in ("!result!") do (
if %%B gtr !RegKey_MaxLength! set "RegKey_MaxLength=%%B"
)
)
REM Set Columns Spacing
set "Space_Count=%SNPID_MaxLength%"
set "SNPID_Space= "
set "LibName_Space= "
set "RegKey_Space= "
:SNPID_Spacing
if "%Space_Count%"=="0" ( set "Space_Count=%LibName_MaxLength%" & goto :LibName_Spacing )
set "SNPID_Space=%SNPID_Space% "
set /a "Space_Count-=1"
goto :SNPID_Spacing
:LibName_Spacing
if "%Space_Count%"=="0" ( set "Space_Count=%RegKey_MaxLength%" & goto :RegKey_Spacing )
set "LibName_Space=%LibName_Space% "
set /a "Space_Count-=1"
goto :LibName_Spacing
:RegKey_Spacing
if "%Space_Count%"=="0" ( goto :Realign_Columns )
set "RegKey_Space=%RegKey_Space% "
set /a "Space_Count-=1"
goto :RegKey_Spacing
REM Columns Alignment
:Realign_Columns
(
for /f "usebackqtokens=1-4 delims=|" %%a in ("%SNPID_TMP_List_To_Realign%") do (
set "SNPID_Aligned=%%a%SNPID_Space%" & set "SNPID_Aligned=!SNPID_Aligned:~0,%SNPID_MaxLength%!"
set "LibName_Aligned=%%b%LibName_Space%" & set "LibName_Aligned=!LibName_Aligned:~0,%LibName_MaxLength%!"
set "RegKey_Aligned=%%c%RegKey_Space%" & set "RegKey_Aligned=!RegKey_Aligned:~0,%RegKey_MaxLength%!"
echo !SNPID_Aligned!^|!LibName_Aligned!^|!RegKey_Aligned!^|%%d
)
)>"%SNPID_List%"
endlocal
REM del "%SNPID_TMP_List%" "%SNPID_TMP_List_To_Order%" "%SNPID_TMP_List_To_Realign%"
pause & exit /b
:strlen
(
(set^ tmp=!String!)
set "len=1"
for %%P in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if "!tmp:~%%P,1!" NEQ "" (
set /a "len+=%%P"
set "tmp=!tmp:~%%P!"
))
)
(
set "result=!len!"
exit /b
)
当
但应仅限于:
165 | Maschine 2
334 | Maschine 2 Essentials
249 | Battery 4
166 | Another Flavour
167 | Another Flavour2
optionally, also
334165166167| Maschine 2
or without... (would like to see both outputs)
意思是:
始终将SNPID与其内部的名称关联,除非内部有值,否则我将SNPID与内部的名称关联
在有或没有味道的情况下省略名字…我需要查看两个不同的解析输出来选择
名称始终在其SNPID编号之上,但中间可能有一些值和不同的行数
当存在风味值时,风味RegKey是产品RegKey
更新:
更新了PS解析的问题尝试,它的工作很好,但我不能解决的味道的事情,太难了我…也不能在UTF8NOBOM输出
"DummyLine" | Out-File "$PSScriptRoot\Parsed_List.txt" -Encoding UTF8
$items = Get-ChildItem "C:\Program Files\Common Files\Native Instruments\Service Center\*.xml"
foreach ($item in $items) {
[xml]$XML_File = Get-Content $item
$XML_File.ProductHints.Product | % {
$Name = $_.Name
$RegKey = $_.RegKey
If (-Not $_.SNPID) {$SNPID = "ThirdParty"} Else {$SNPID = $_.SNPID}
If (-Not $_.Company) {$Company = "Not specified"} Else {$Company = $_.Company}
If ($SNPID -eq "334165") {$Name = "Maschine 2 Essential";$SNPID = "165"}
"$SNPID`|$Name`|$Company`|$RegKey`|Location" | Out-File "$PSScriptRoot\Parsed_List.txt" -append -Encoding UTF8
}
}
你的描述既混乱又不完整。如果一个文件包含多个SNPID和名称,是否要省略一条记录?哪一个?第一个 也许此代码可以帮助您:
@echo off
setlocal
rem Initialize variables
set "i=0"
for /F "delims==" %%a in ('set A_ 2^>NUL') do set "%%a="
rem Process all files
for /F "delims=" %%a in ('dir /S /B /A:-D *.xml') do (
rem Accumulate records for this file
setlocal EnableDelayedExpansion
for /F "usebackq tokens=1-3 delims=<>" %%E in ("%%a") do (
if "%%F" == "Name" (
set /A i+=1
set "A_Name[!i!]=%%G"
) else if "%%F" == "RegKey" (
set "A_RegKey[!i!]=%%G"
) else if "%%F" == "SNPID" (
set "A_SNPID[!i!]=%%G"
set "A_Order[%%G]=!i!"
if !i! equ 1 set "first=%%G"
)
)
rem If there are more than 1 records: omit the first one
if !i! gtr 1 set "A_Order[!first!]="
rem Show records
echo ============ File %%a ================
for /F "tokens=2 delims==" %%i in ('set A_Order[') do (
echo !A_SNPID[%%i]! !A_Name[%%i]!
)
echo/
rem Reset all variables
endlocal
)
pause
我正在尝试基于.xml文件为已安装的库生成.txt报告。它应该报告库SNPID号|库名称|注册表项|库路径。按升数排序
我不太熟悉PowerShell及其功能,但由于批处理的局限性,使用本机批处理函数解析XML是一个非常糟糕的主意。我想您已经亲眼看到了批处理脚本会变得多么复杂。
更糟糕的是,戴夫·本汉姆用“jrepl.bat”完成了惊人的工作,没有冒犯到他
请使用真正的XML解析器,如:
如果我没弄错你的问题,这就是你想要的:
-抓取产品以及风味元素节点并按SNPID排序。
-抓住前面提到的兄弟姐妹,加入他们,用|分开
目前,我无法帮助您处理第4个元素| Library Path,因为我没有这些注册表项
…并最终对齐列
这有点困难,但这是可能的。基本上可以归结为:
-将上面的输出放在一系列数组中,并分配给一个变量。
-计算每个“列”的最大宽度。
-为每个值添加空白以达到此宽度
xidel -s input.xml --xquery ^"^
let $a:=for $x in (//Product,//Flavour)^
order by $x/SNPID^
return $x/[^
SNPID,^
Name,^
(RegKey,../RegKey)^
],^
$b:=(1 to count($a)) ! max(^
$a(.) ! string-length()^
)^
return^
$a ! join(^
for $x at $i in .() return^
substring(^
$x^|^|string-join((1 to $b[$i]) ! ' '),^
1,$b[$i]^
),^
' ^| '^
)^
"
165 | Maschine 2 Essentials | Maschine 2
166 | Another Flavour | Maschine 2
167 | Another Flavour2 | Maschine 2
249 | Battery 4 | Battery
334 | Maschine 2 | Maschine 2
334165166167 | Maschine 2 | Maschine 2
这是一个“修饰”查询,每行末尾和每个|都有必要的转义字符,您可以在命令提示下直接复制粘贴
另请参见。好的,不要使用批处理文件来解析XML数据,请使用一种语言,例如,本机支持此类数据格式的语言…谢谢,我用powershell更新了问题…它解析正确,但仍在努力解决问题,并以UTF8BOM而不是UTF8输出,所以我需要输出第一个伪行,因为批处理后的第一个字符很奇怪,那么批处理脚本的执行速度也比for/f循环慢。对不起,这是我在这里的第一篇文章……我意识到了这一点。事实上,我不想省略任何名称,除非有值,否则我可能会在更新.xml示例和预期结果之前省略名称和SNPID。无论如何,谢谢你,你的帖子总是很好,可以学到很多东西
165 | Maschine 2
334 | Maschine 2 Essentials
249 | Battery 4
166 | Another Flavour
167 | Another Flavour2
optionally, also
334165166167| Maschine 2
or without... (would like to see both outputs)
"DummyLine" | Out-File "$PSScriptRoot\Parsed_List.txt" -Encoding UTF8
$items = Get-ChildItem "C:\Program Files\Common Files\Native Instruments\Service Center\*.xml"
foreach ($item in $items) {
[xml]$XML_File = Get-Content $item
$XML_File.ProductHints.Product | % {
$Name = $_.Name
$RegKey = $_.RegKey
If (-Not $_.SNPID) {$SNPID = "ThirdParty"} Else {$SNPID = $_.SNPID}
If (-Not $_.Company) {$Company = "Not specified"} Else {$Company = $_.Company}
If ($SNPID -eq "334165") {$Name = "Maschine 2 Essential";$SNPID = "165"}
"$SNPID`|$Name`|$Company`|$RegKey`|Location" | Out-File "$PSScriptRoot\Parsed_List.txt" -append -Encoding UTF8
}
}
@echo off
setlocal
rem Initialize variables
set "i=0"
for /F "delims==" %%a in ('set A_ 2^>NUL') do set "%%a="
rem Process all files
for /F "delims=" %%a in ('dir /S /B /A:-D *.xml') do (
rem Accumulate records for this file
setlocal EnableDelayedExpansion
for /F "usebackq tokens=1-3 delims=<>" %%E in ("%%a") do (
if "%%F" == "Name" (
set /A i+=1
set "A_Name[!i!]=%%G"
) else if "%%F" == "RegKey" (
set "A_RegKey[!i!]=%%G"
) else if "%%F" == "SNPID" (
set "A_SNPID[!i!]=%%G"
set "A_Order[%%G]=!i!"
if !i! equ 1 set "first=%%G"
)
)
rem If there are more than 1 records: omit the first one
if !i! gtr 1 set "A_Order[!first!]="
rem Show records
echo ============ File %%a ================
for /F "tokens=2 delims==" %%i in ('set A_Order[') do (
echo !A_SNPID[%%i]! !A_Name[%%i]!
)
echo/
rem Reset all variables
endlocal
)
pause
============ File C:\Users\Antonio\Documents\ASMB\Modern Batch File Programming\BORRAME\File1.xml ================
249 Battery 4
============ File C:\Users\Antonio\Documents\ASMB\Modern Batch File Programming\BORRAME\File2.xml ================
165 Maschine 2 Essentials
334 Maschine 2
xidel -s input.xml --xquery "for $x in (//Product,//Flavour) order by $x/SNPID return $x/join((SNPID,Name,(RegKey,../RegKey)),' | ')"
165 | Maschine 2 Essentials | Maschine 2
166 | Another Flavour | Maschine 2
167 | Another Flavour2 | Maschine 2
249 | Battery 4 | Battery
334 | Maschine 2 | Maschine 2
334165166167 | Maschine 2 | Maschine 2
xidel -s input.xml --xquery ^"^
let $a:=for $x in (//Product,//Flavour)^
order by $x/SNPID^
return $x/[^
SNPID,^
Name,^
(RegKey,../RegKey)^
],^
$b:=(1 to count($a)) ! max(^
$a(.) ! string-length()^
)^
return^
$a ! join(^
for $x at $i in .() return^
substring(^
$x^|^|string-join((1 to $b[$i]) ! ' '),^
1,$b[$i]^
),^
' ^| '^
)^
"
165 | Maschine 2 Essentials | Maschine 2
166 | Another Flavour | Maschine 2
167 | Another Flavour2 | Maschine 2
249 | Battery 4 | Battery
334 | Maschine 2 | Maschine 2
334165166167 | Maschine 2 | Maschine 2