1

I have XML files where I want to replace certain strings.

The replacement source is a CSV file that contains 2 columns

old       |           new
-------------------------
OldPart1  |  NewPartName1
OldPart2  |  NewPartName2
OldPart3  |  NewPartName3

I want to replace all occurances of old with new in the XML files. I guess it does not really matter if the files are XML or just text. The replacement strings don't collide with XML tag names.

5
  • Have you tried simple text editors such as Notepad and Notepad++?
    – ComFreek
    Aug 2, 2014 at 8:12
  • Yes, it did not find a method for mass replacements
    – juergen d
    Aug 2, 2014 at 10:07
  • In Notepad++ press Ctrl+H to open the search & replace dialog.
    – ComFreek
    Aug 2, 2014 at 10:24
  • I know. And where do I choose the CSV file to replace 1000 different strings one after each other?
    – juergen d
    Aug 2, 2014 at 10:25
  • I misunderstood you, sorry. I don't think there are any editors which support your special requirement. I've experimented a little bit with PowerShell (it's fun). Please see my answer.
    – ComFreek
    Aug 2, 2014 at 11:06

2 Answers 2

2

A little PowerShell magic.

Additional comments:

  • Your CSV file must not contain headers and must use ; as delimiters.
  • Your input and CSV file must both be encoded in UTF-8 or UTF-16. Other encodings can't be automatically guessed by PowerShell.
  • The script won't exit if you specify invalid filenames. Don't expect a nice error dialog to open :)
<#
  Copied from: http://blogs.technet.com/b/heyscriptingguy/archive/2009/09/01/hey-scripting-guy-september-1.aspx
  Many thanks to the Scripting Guy :)
  Changes:
    - Added a title parameter and assigned it to $OpenFileDialog.title
    - Changed the function's name to Get-OpenFile
#>
Function Get-OpenFile($initialDirectory, $title)
{   
 [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
 Out-Null

 $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
 $OpenFileDialog.title = $title;
 $OpenFileDialog.initialDirectory = $initialDirectory
 $OpenFileDialog.filter = "All files (*.*)| *.*"
 $OpenFileDialog.ShowDialog() | Out-Null
 $OpenFileDialog.filename
} #end function Get-FileName

Function Get-SaveFile($initialDirectory, $title)
{   
 [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") |
 Out-Null

 $OpenFileDialog = New-Object System.Windows.Forms.SaveFileDialog
 $OpenFileDialog.title = $title;
 $OpenFileDialog.initialDirectory = $initialDirectory
 $OpenFileDialog.filter = "All files (*.*)| *.*"
 $OpenFileDialog.ShowDialog() | Out-Null
 $OpenFileDialog.filename
} #end function Get-OpenFile

# $PSScriptRoot is only available for PowerShell >= 3
# Fallback needed
$scriptDir = $PSScriptRoot

$inputFile = Get-OpenFile -initialDirectory $scriptDir -title "Choose your input file"
$csvFile = Get-OpenFile -initialDirectory $scriptDir -title "Choose your CSV file"

$inputStr = [Io.File]::ReadAllText($inputFile);
$csvData = Import-Csv $csvFile -Header @("Needle", "Replacement") -Delimiter ';'

$csvData | % {
    $inputStr = $inputStr.Replace($_.needle, $_.replacement);
}

$outputFilename = Get-SaveFile -initialDirectory $scriptDir -title "Save your file"
$inputStr | Out-File -FilePath $outputFilename
1

Using python, (available on/for most platforms and free), and assuming that your xml file will fit in memory and that the separator is , with no space:

with open(r"XML/File/Name").read() as xml: 
    with open(r"Path/To/Output/File", "w") as outfile:
        for line in open(r"CSV/File/Name").readlines():
            (orig, replacement) = ','.split(line) # Change ',' to your separator
            xml.replace(orig, replacement)
            outfile.writeline(line)

I am sure that there are better/more generic ways to do this but it is late at the moment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.