If </sometag>
appears only once in your XML and if it won't screw up the hierarchy inserting your new <tag>
node on the line before, you could just loop through your XML file with a for /F
loop, checking whether each line contains </sometag>
. When found, simply echo your new <tag>
prior to echoing the matched line.
@echo off
setlocal
>"newfile.xml" (
for /f "usebackq delims=" %%I in ("xmlfile.xml") do (
set "line=%%I"
setlocal enabledelayedexpansion
if not "!line!"=="!line:/sometag=!" (
echo ^<tag attr_name="long filename" /^>
)
endlocal
echo(%%I
)
)
type "newfile.xml"
But really, assuming your XML is fully valid, the most elegant solution is to parse the XML as structured data, rather than as complicated text to hack and scrape. That way it doesn't matter whether your code is beautified, minified, uglified, or whatever. The parser still understands it, regardless of indentation and line breaks. You can do this with languages already built into Windows -- VBScript, JScript, PowerShell, C#, and the list goes on. Batch might be the only language with which you're familiar, but it isn't the only language available in a base install of Windows. Here's a quick and dirty batch + PowerShell hybrid script to demonstrate. (Save it with a .bat extension.)
<# : batch portion (within a multiline PowerShell comment)
@echo off & setlocal
set "infile=test.xml"
set "parentNode=sometag"
set "newTag=tag"
set "newAttr=attr_name"
set "attrVal=long filename"
set "outfile=new.xml"
powershell -noprofile -noninteractive "iex (${%~f0} | out-string)"
type "%outfile%"
goto :EOF
: end batch (multiline comment) / begin PowerShell hybrid code #>
[xml]$xml = gc $env:infile
$parent = $xml.documentElement.selectSingleNode("//$env:parentNode")
$new = $xml.createElement($env:newTag)
[void]$new.setAttribute($env:newAttr, $env:attrVal)
[void]$parent.appendChild($new)
$xml.save($env:outfile)