การแก้ไข xml ด้วย powershell

การแก้ไขข้อมูลในไฟล์ xml บน Windows ไม่ใช่เรื่องง่าย ถ้ามีข้อมูลจำนวนมาก และยิ่งถ้ามีหลายไฟล์ ก็ยิ่งทำให้ต้องใช้เวลาในการแก้ไขไม่ใช่น้อย

ทางออกคือการใช้ PowerShell ซึ่งมีมาแล้วใน Windows สามารถเขียนคำสั่งใน command line หรือจะเขียนเป็น script และสั่งให้ทำงานได้ เช่นกัน นอกจากนี้ ยังมี PowerShell ISE ซึ่งมีหน้าจอให้เขียนคำสั่ง หรือ Script ก็ได้


ปัจจุบัน (2564) คือ Windows PowerShell 7.1.3 ยังไม่มี IDE ต้องใช้ผ่านทาง Command Line เท่านั้น (รุ่นที่ติดมากับ Windows10 ไม่ใช่รุ่นปัจจุบัน ถ้าต้องการใช้ ต้องไป download มาติดตั้งใหม่

การเปิดใช้งาน

  1. คลิกขวาที่ปุ่ม เริ่มต้น และ  Windows PowerShell (Admin)


  2. หรือถ้ามีช่องค้นหา ก็พิมพ์คำว่า PowerShell และเลือกเปิดแบบ Admin (Run as adminstrator)


  3. ถ้าเป็นการใช้งานครั้งแรก อาจจะมีปัญหาเกี่ยวกับ ExecutionPolicy ให้เปลี่ยน ExecutionPolicy เป็น Unrestricted โดยพิมพ์ ในหน้าของ PowerShell ดังนี้


  4. เนื่องจาก ExecutionPolicy เป็นการป้องกันเกี่ยวกับความปลอดภัย เพื่อป้องกันไม่ให้โปรแกรมที่เป็นอันตรายต่อเครื่องคอมพิวเตอร์ โปรแกรม PowerShell จะถามให้ยืนยัน ให้คลิก Y 


  5. เมื่อโปรแกรมพร้อม จะเห็นคำว่า PS ให้พิมพ์ชื่อไฟล์ script ที่เขียนไว้ โดยต้องระบุที่อยู่ให้ชัดเจนด้วย แล้วกด enter



  6. ถ้าไม่มีปัญหาอะไร โปรแกรมจะแสดงเป็น Command Prompt


  7. แต่ถ้ามี Error โปรแกรมจะแสดงข้อผิดพลาด พร้อมทั้งอธิบายว่า ผิดพลาดอย่างไร บางครั้งก็มีข้อเสนอแนะให้ด้วย
  8. จากนั้น จึงพิมพ์ชื่อของไฟล์ .ps1 (พร้อมระบุที่อยู่ของไฟล์ .ps1 ให้ถูกต้องด้วย) แล้วกด Enter เพื่อให้ ทำงานตามสคริป
  9. อีกทางเลือก อาจจะคัดลอกสคริป มาวางไว้ใน หน้าต่างของ PowerShell แล้วกด Enter ก็ได้ เช่น


    เมื่อกด Enter โปรแกรม PowerShell จะทำงาน ดังภาพ


ตัวอย่าง Script

ใช้ text editor เขียนคำสั่งข้างล่าง และบันทึกไว้ เป็นไฟล์ นามสกุล .ps1

สมมติว่า ต้องการแก้ไข <qNum> ในไฟล์ xml ซึ่งมีโครงสร้างดังนี้


Script:

#ไฟล์ที่ต้องการแก้ไข
$inFile = "D:\_000fromandroid_new\2_th_1_word22.xml" 
# ไฟล์ที่แก้ไขแล้ว ถ้าต้องการให้แทนที่ไฟล์เดิม ก็ใช้ชื่อเดิม
$outFile = "D:\_000fromandroid_new\2_th_1_word22_updated.xml" 
# Get-Content คือให้อ่านไฟล์ xml เก็บใน memory
$xml = [xml] (Get-Content -Raw $inFile)
# กำหนดค่าที่ต้องการให้เปลี่ยน ในกรณีนี้ เราจะเพิ่มตัวเลขเพื่อไม่ให้ซ้ำกัน
$x=1
#ให้เลือก parent node ของ node ที่จะเปลี่ยน
#และวน โดยใช้ ForEach
$xml.SelectNodes('//thisQuestion').ForEach({
 # เปลี่ยนค่าเป็นตัวแปรชนิดข้อความ
 $new_qNum = ($x.ToString())
  # update ค่าใน <qNum> ซึ่งเป็นลูกของ <thisQuestion>
  $_.qNum =  $new_qNum
# เพิ่มค่า เพื่อจะได้ไม่ซ้ำกัน
  $x++
})

# เสร็จแล้ว บันทึก จะได้ไฟล์ xml ที่แก้ไขแล้ว
$xml.Save($outFile)


ในกรณีที่ต้องการเปลี่ยนครั้งละหลาย ๆ ไฟล์ 

ให้เอาไฟล์ทั้งหมดไปไว้ในห้อง เดียวกัน และให้เปลี่ยนทุกไฟล์

ตัวอย่าง script


$files = Get-ChildItem "D:\_00tmp\"
$x=1
foreach ($f in $files){
$xml = [xml] (Get-Content -Raw $f)
$xml.SelectNodes('//thisQuestion').ForEach({
  $new_qNum = ($first + $x.ToString() + $last)
  $_.qNum =  $new_qNum
  $x++
})
$outfile = $f.FullName #แทนที่ไฟลฺ์เดิม
$xml.Save($outFile)
}

ในกรณีที่ต้องการเปลี่ยนข้อความ ในไฟล์ .txt หรือ html ครั้งละหลาย ๆ ไฟล์ เช่น ต้องการเปลี่ยนจาก คำว่า assets/images/ เป็น images/ ให้นำไฟล์ที่ต้องการเปลี่ยนไปไว้รวมกันในห้องเดียวกัน เช่น ห้อง D:\_01 แล้วเขียนสคริป ดังนี้

$fileNames = Get-ChildItem "D:\_01" -Recurse |
 select -expand fullname

foreach ($filename in $filenames) 
{
  (  Get-Content $fileName) -replace 'assets/images/', 'images/' | Set-Content $fileName
}



ข้อมูลจาก 
https://stackoverflow.com/questions/47336537/finding-and-updating-xml-node-in-powershell


ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

อุปมา อุปไมย สำนวนการเปรียบเทียบ ของไทย

เทคนิคการทำ ข้อสอบ อนุกรม ของ ก.พ.

แนวข้อสอบ เงื่อนไขสัญลักษณ์