PowerShell
XML 파일 작업
수색…
XML 파일 액세스
<!-- file.xml -->
<people>
<person id="101">
<name>Jon Lajoie</name>
<age>22</age>
</person>
<person id="102">
<name>Lord Gaben</name>
<age>65</age>
</person>
<person id="103">
<name>Gordon Freeman</name>
<age>29</age>
</person>
</people>
XML 파일로드
XML 파일을로드하려면 다음 중 하나를 사용할 수 있습니다.
# First Method
$xdoc = New-Object System.Xml.XmlDocument
$file = Resolve-Path(".\file.xml")
$xdoc.load($file)
# Second Method
[xml] $xdoc = Get-Content ".\file.xml"
# Third Method
$xdoc = [xml] (Get-Content ".\file.xml")
XML을 객체로 액세스하기
PS C:\> $xml = [xml](Get-Content file.xml)
PS C:\> $xml
PS C:\> $xml.people
person
--------
{Jon Lajoie, Lord Gaben, Gordon Freeman}
PS C:\> $xml.people.person
id name age
-- ---- ---
101 Jon Lajoie 22
102 Lord Gaben 65
103 Gordon Freeman 29
PS C:\> $xml.people.person[0].name
Jon Lajoie
PS C:\> $xml.people.person[1].age
65
PS C:\> $xml.people.person[2].id
103
XPath로 XML에 접근하기
PS C:\> $xml = [xml](Get-Content file.xml)
PS C:\> $xml
PS C:\> $xml.SelectNodes("//people")
person
--------
{Jon Lajoie, Lord Gaben, Gordon Freeman}
PS C:\> $xml.SelectNodes("//people//person")
id name age
-- ---- ---
101 Jon Lajoie 22
102 Lord Gaben 65
103 Gordon Freeman 29
PS C:\> $xml.SelectSingleNode("people//person[1]//name")
Jon Lajoie
PS C:\> $xml.SelectSingleNode("people//person[2]//age")
65
PS C:\> $xml.SelectSingleNode("people//person[3]//@id")
103
XPath를 사용하여 네임 스페이스가 포함 된 XML에 액세스
PS C:\> [xml]$xml = @"
<ns:people xmlns:ns="http://schemas.xmlsoap.org/soap/envelope/">
<ns:person id="101">
<ns:name>Jon Lajoie</ns:name>
</ns:person>
<ns:person id="102">
<ns:name>Lord Gaben</ns:name>
</ns:person>
<ns:person id="103">
<ns:name>Gordon Freeman</ns:name>
</ns:person>
</ns:people>
"@
PS C:\> $ns = new-object Xml.XmlNamespaceManager $xml.NameTable
PS C:\> $ns.AddNamespace("ns", $xml.DocumentElement.NamespaceURI)
PS C:\> $xml.SelectNodes("//ns:people/ns:person", $ns)
id name
-- ----
101 Jon Lajoie
102 Lord Gaben
103 Gordon Freeman
XmlWriter ()를 사용하여 XML 문서 만들기
# Set The Formatting
$xmlsettings = New-Object System.Xml.XmlWriterSettings
$xmlsettings.Indent = $true
$xmlsettings.IndentChars = " "
# Set the File Name Create The Document
$XmlWriter = [System.XML.XmlWriter]::Create("C:\YourXML.xml", $xmlsettings)
# Write the XML Decleration and set the XSL
$xmlWriter.WriteStartDocument()
$xmlWriter.WriteProcessingInstruction("xml-stylesheet", "type='text/xsl' href='style.xsl'")
# Start the Root Element
$xmlWriter.WriteStartElement("Root")
$xmlWriter.WriteStartElement("Object") # <-- Start <Object>
$xmlWriter.WriteElementString("Property1","Value 1")
$xmlWriter.WriteElementString("Property2","Value 2")
$xmlWriter.WriteStartElement("SubObject") # <-- Start <SubObject>
$xmlWriter.WriteElementString("Property3","Value 3")
$xmlWriter.WriteEndElement() # <-- End <SubObject>
$xmlWriter.WriteEndElement() # <-- End <Object>
$xmlWriter.WriteEndElement() # <-- End <Root>
# End, Finalize and close the XML Document
$xmlWriter.WriteEndDocument()
$xmlWriter.Flush()
$xmlWriter.Close()
출력 XML 파일
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/xsl' href='style.xsl'?>
<Root>
<Object>
<Property1>Value 1</Property1>
<Property2>Value 2</Property2>
<SubObject>
<Property3>Value 3</Property3>
</SubObject>
</Object>
</Root>
현재 XMLDocument에 XML 스 니핏 추가하기
샘플 데이터
XML 문서
먼저, 현재 디렉토리에 " books.xml "이라는 샘플 XML 문서를 정의 해 보겠습니다.
<?xml version="1.0" encoding="UTF-8"?> <books> <book> <title>Of Mice And Men</title> <author>John Steinbeck</author> <pageCount>187</pageCount> <publishers> <publisher> <isbn>978-88-58702-15-4</isbn> <name>Pascal Covici</name> <year>1937</year> <binding>Hardcover</binding> <first>true</first> </publisher> <publisher> <isbn>978-05-82461-46-8</isbn> <name>Longman</name> <year>2009</year> <binding>Hardcover</binding> </publisher> </publishers> <characters> <character name="Lennie Small" /> <character name="Curley's Wife" /> <character name="George Milton" /> <character name="Curley" /> </characters> <film>True</film> </book> <book> <title>The Hunt for Red October</title> <author>Tom Clancy</author> <pageCount>387</pageCount> <publishers> <publisher> <isbn>978-08-70212-85-7</isbn> <name>Naval Institute Press</name> <year>1984</year> <binding>Hardcover</binding> <first>true</first> </publisher> <publisher> <isbn>978-04-25083-83-3</isbn> <name>Berkley</name> <year>1986</year> <binding>Paperback</binding> </publisher> <publisher> <isbn>978-08-08587-35-4</isbn> <name>Penguin Putnam</name> <year>2010</year> <binding>Paperback</binding> </publisher> </publishers> <characters> <character name="Marko Alexadrovich Ramius" /> <character name="Jack Ryan" /> <character name="Admiral Greer" /> <character name="Bart Mancuso" /> <character name="Vasily Borodin" /> </characters> <film>True</film> </book> </books>
새 데이터
우리가하고 싶은 일은이 문서에 몇 권의 새로운 책을 추가하는 것입니다. Tom Clancy의 Patriot Games (예, Clancy의 작품 팬입니다 ^^)와 Sci-Fi가 좋아하는 영화 : Hitchhiker 's Galaxy Guide Douglas Adams는 Zaphod Beeblebrox가 읽는 것만으로도 재미 있기 때문입니다.
어쨌든 우리는 새 책의 데이터를 가져 와서 PSCustomObjects 목록으로 저장했습니다.
$newBooks = @( [PSCustomObject] @{ "Title" = "Patriot Games"; "Author" = "Tom Clancy"; "PageCount" = 540; "Publishers" = @( [PSCustomObject] @{ "ISBN" = "978-0-39-913241-4"; "Year" = "1987"; "First" = $True; "Name" = "Putnam"; "Binding" = "Hardcover"; } ); "Characters" = @( "Jack Ryan", "Prince of Wales", "Princess of Wales", "Robby Jackson", "Cathy Ryan", "Sean Patrick Miller" ); "film" = $True; }, [PSCustomObject] @{ "Title" = "The Hitchhiker's Guide to the Galaxy"; "Author" = "Douglas Adams"; "PageCount" = 216; "Publishers" = @( [PSCustomObject] @{ "ISBN" = "978-0-33-025864-7"; "Year" = "1979"; "First" = $True; "Name" = "Pan Books"; "Binding" = "Hardcover"; } ); "Characters" = @( "Arthur Dent", "Marvin", "Zaphod Beeblebrox", "Ford Prefect", "Trillian", "Slartibartfast", "Dirk Gently" ); "film" = $True; } );
템플릿
이제 우리는 새로운 데이터가 들어갈 수 있도록 몇 개의 스켈레톤 XML 구조를 정의해야합니다. 기본적으로 각 데이터 목록에 대해 뼈대 / 템플릿을 만들려고합니다. 이 예에서는 책, 캐릭터 및 게시자 용 템플릿이 필요하다는 것을 의미합니다. 또한 이것을 사용하여 film
태그의 값과 같은 몇 가지 기본값을 정의 할 수 있습니다.
$t_book = [xml] @' <book> <title /> <author /> <pageCount /> <publishers /> <characters /> <film>False</film> </book> '@; $t_publisher = [xml] @' <publisher> <isbn/> <name/> <year/> <binding/> <first>false</first> </publisher> '@; $t_character = [xml] @' <character name="" /> '@;
우리는 준비가 끝났습니다.
새 데이터 추가
이제 예제 데이터로 설정 했으므로 XML 문서 객체에 사용자 정의 객체를 추가해 보겠습니다.
# Read the xml document $xml = [xml] Get-Content .\books.xml; # Let's show a list of titles to see what we've got currently: $xml.books.book | Select Title, Author, @{N="ISBN";E={If ( $_.Publishers.Publisher.Count ) { $_.Publishers.publisher[0].ISBN} Else { $_.Publishers.publisher.isbn}}};; # Outputs: # title author ISBN # ----- ------ ---- # Of Mice And Men John Steinbeck 978-88-58702-15-4 # The Hunt for Red October Tom Clancy 978-08-70212-85-7 # Let's show our new books as well: $newBooks | Select Title, Author, @{N="ISBN";E={$_.Publishers[0].ISBN}}; # Outputs: # Title Author ISBN # ----- ------ ---- # Patriot Games Tom Clancy 978-0-39-913241-4 # The Hitchhiker's Guide to the Galaxy Douglas Adams 978-0-33-025864-7 # Now to merge the two: ForEach ( $book in $newBooks ) { $root = $xml.SelectSingleNode("/books"); # Add the template for a book as a new node to the root element [void]$root.AppendChild($xml.ImportNode($t_book.book, $true)); # Select the new child element $newElement = $root.SelectSingleNode("book[last()]"); # Update the parameters of that new element to match our current new book data $newElement.title = [String]$book.Title; $newElement.author = [String]$book.Author; $newElement.pageCount = [String]$book.PageCount; $newElement.film = [String]$book.Film; # Iterate through the properties that are Children of our new Element: ForEach ( $publisher in $book.Publishers ) { # Create the new child publisher element # Note the use of "SelectSingleNode" here, this allows the use of the "AppendChild" method as it returns # a XmlElement type object instead of the $Null data that is currently stored in that leaf of the # XML document tree [void]$newElement.SelectSingleNode("publishers").AppendChild($xml.ImportNode($t_publisher.publisher, $true)); # Update the attribute and text values of our new XML Element to match our new data $newPublisherElement = $newElement.SelectSingleNode("publishers/publisher[last()]"); $newPublisherElement.year = [String]$publisher.Year; $newPublisherElement.name = [String]$publisher.Name; $newPublisherElement.binding = [String]$publisher.Binding; $newPublisherElement.isbn = [String]$publisher.ISBN; If ( $publisher.first ) { $newPublisherElement.first = "True"; } } ForEach ( $character in $book.Characters ) { # Select the characters xml element $charactersElement = $newElement.SelectSingleNode("characters"); # Add a new character child element [void]$charactersElement.AppendChild($xml.ImportNode($t_character.character, $true)); # Select the new characters/character element $characterElement = $charactersElement.SelectSingleNode("character[last()]"); # Update the attribute and text values to match our new data $characterElement.name = [String]$character; } } # Check out the new XML: $xml.books.book | Select Title, Author, @{N="ISBN";E={If ( $_.Publishers.Publisher.Count ) { $_.Publishers.publisher[0].ISBN} Else { $_.Publishers.publisher.isbn}}}; # Outputs: # title author ISBN # ----- ------ ---- # Of Mice And Men John Steinbeck 978-88-58702-15-4 # The Hunt for Red October Tom Clancy 978-08-70212-85-7 # Patriot Games Tom Clancy 978-0-39-913241-4 # The Hitchhiker's Guide to the Galaxy Douglas Adams 978-0-33-025864-7
이제 우리는 XML을 디스크 나 화면 또는 웹에 쓸 수 있습니다!
이익
이것은 모든 사람들을위한 절차가 아니지만, [void]$xml.SelectSingleNode("/complicated/xpath/goes[here]").AppendChild($xml.CreateElement("newElementName")
의 전체 무리를 피하는 데 도움이되는 것으로 나타났습니다 [void]$xml.SelectSingleNode("/complicated/xpath/goes[here]").AppendChild($xml.CreateElement("newElementName")
다음에 $xml.SelectSingleNode("/complicated/xpath/goes/here/newElementName") = $textValue
이 예제에서 자세히 설명하는 메서드는 일반 인간을 위해 더 명확하고 파싱하기 쉽다고 생각합니다.
개량
각 섹션을 별도의 템플릿으로 분리하는 대신 하위 요소가 포함 된 요소를 포함하도록 템플릿을 변경할 수도 있습니다. 목록을 반복 할 때 이전 요소를 복제하는 데주의를 기울여야합니다.