드라이버 정보가 포함 된 XML 문서를 구성하려고합니다. 다음은 내가 작업중인 작업의 예입니다.
<?xml version="1.0" encoding="utf-8"?>
<IncludeFragment xmlns:p="http://schemas.microsoft.com/someschema">>
<FFUDriver>
<Component>
<Package>
<p:PackageName>Intel.Display.Driver</PackageName>
<p:PackageFeedName>Feed</PackageFeedName>
<p:Version>10.24.0.1638</Version>
<p:Flavor>release</Flavor>
</Package>
</Component>
</FFUDriver>
<FFUDriver>
<Component>
<Package>
<p:PackageName>Intel.Audio.Driver</PackageName>
<p:PackageFeedName>Feed</PackageFeedName>
<p:Flavor>release</Flavor>
<p:Version>10.24.0.1638</Version>
<p:CabName>Intel.Audio.cab</CabName>
</Package>
</Component>
</FFUDriver>
</IncludeFragment>
각 패키지의 요소를 다음 순서로 정렬해야합니다.
내 예제 XML 코드에서와 같이 패키지의 일부 요소는 이미 적절한 순서로되어 있지만 일부는 그렇지 않습니다. 또한 각 패키지는 PackageName을 기준으로 알파벳 순서로 정렬해야합니다. 저는 PowerShell에서 XML로 작업하는 것이 처음이며이 작업을 수행하는 방법을 평생 알 수 없습니다.
다른 요구 사항은 모든 <CabName>
요소 를 찾아 삭제하는 것 입니다. 나는 그것을 알아 냈다. 불행히도 아래에있는 코드는 자식 요소 <Package>
중 하나가이면 요소의 모든 자식 요소를 삭제합니다 <CabName>
. 만 선택하고 삭제하는 구문을 알아낼 수없는 것 같습니다 <CabName>
.
$Path = 'C:\Drivers.xml'
$xml = New-Object -TypeName XML
$xml.Load($Path)
$xml.SelectNodes('//Package[CabName]') | ForEach-Object {
$_.ParentNode.RemoveChild($_)
}
$xml.Save('C:\Test.xml')
업데이트 : Ansgar Wiechers의 도움으로 완성 된 코드는 다음과 같습니다. 작업하는 일부 문서에 네임 스페이스가 포함되어 있으므로 예제 XML 데이터를 업데이트하여 네임 스페이스를 포함했습니다. 아래 코드는 네임 스페이스를 처리합니다. 유사한 문제 / 질문이있는 다른 사람에게 도움이되기를 바랍니다.
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $True, Position = 0)]
[ValidateScript({
$_ = $_ -replace '"', ""
if (-Not (Test-Path -Path $_ -PathType Leaf))
{
Throw "`n `n$_ `n `nThe specified file or path does not exist. Check the file name and path, and then try again."
}
return $True
})]
[System.String]$XMLPath,
[Parameter(Mandatory = $False, Position = 1)]
[System.String]$nsPrefix = "p",
[Parameter(Mandatory = $False, Position = 2)]
[System.String]$nsURI = "http://schemas.microsoft.com/someschema"
)
# Remove quotes from full path name, if they are present
$XMLPath = $XMLPath -replace '"', ""
$xml = New-Object -TypeName XML
$xml.Load($XMLPath)
$ns = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
$ns.AddNamespace($nsPrefix, $nsURI)
# Delete all CabName elements
$xml.SelectNodes('//p:CabName', $ns) | ForEach-Object {
$_.ParentNode.RemoveChild($_) | Out-Null
}
# Sort each Package element's child nodes based on custom order
$SortList = 'p:PackageName', 'p:PackageFeedName', 'p:Version', 'p:Flavor'
$xml.SelectNodes('//Package') | ForEach-Object {
$parent = $_
$SortList | ForEach-Object {
$child = $parent.RemoveChild($parent.SelectSingleNode("./$_", $ns))
$parent.AppendChild($child)
}
} | Out-Null
# Sort each Package element in alphabetical order based on its child node PackageName
$PackageNameList = $xml.SelectNodes('//p:PackageName', $ns) | Select-Object -Expand '#text' | Sort-Object
$xml.SelectNodes('//IncludeFragment') | ForEach-Object {
$parent = $_
$PackageNameList | ForEach-Object {
$child = $parent.RemoveChild($parent.SelectSingleNode("./FFUDriver[Component/Package/p:PackageName/text()='$_']", $ns))
$parent.AppendChild($child)
}
} | Out-Null
$XMLPath = $XMLPath -replace ".xml", "_sorted.xml"
$xml.Save($XMLPath)
Write-Host "`nSorting complete. Sorted XML document saved under $XMLPath" -ForegroundColor Green
보유한 코드는 <Package>
해당 노드의 <CabName>
모든 하위 요소뿐만 아니라 하위 요소가있는 모든 노드를 삭제합니다 . 이는 자식 노드 를 포함하는 //Package[CabName]
모든 <Package>
노드 와 일치 하기 때문 <CabName>
입니다. 실제로 일치시키려는 <CabName>
것은 <Package>
부모 노드 가있는 모든 노드입니다 .
$xml.SelectNodes('./Package/CabName') | ForEach-Object {
$_.ParentNode.RemoveChild($_) | Out-Null
}
또한 일반적으로 XML에서 요소의 순서는 중요하지 않으므로 요소를 정렬하는 것은 의미가 없습니다. 그러나 어떤 이유로 특정 순서로 자식 노드가 있어야하는 경우 원하는 순서로 제거하고 추가하여 요소를 정렬 할 수 있습니다.
# names of the child nodes in the desired order
$nodenames = 'PackageName', 'PackageFeedName', 'Version', 'Flavor'
$xml.SelectNodes('//Package') | ForEach-Object {
$parent = $_
$nodenames | ForEach-Object {
$child = $parent.RemoveChild($parent.SelectSingleNode("./$_"))
$parent.AppendChild($child)
}
}
당신은 또한 원하는 경우 <Driver>
노드는 패키지 이름으로 분류하면 패키지 이름의 정렬 된 목록을 구축하는 최초의 필요성 :
$xml.SelectNodes('//PackageName') | Select-Object -Expand '#text' | Sort-Object
그런 다음 위와 동일한 기술을 사용하여 <Driver>
노드에서 노드 를 제거하고 추가 <Drivers>
합니다. 이 경우 필터 패턴을 사용해야합니다.
"./Driver[Component/Package/PackageName/text()='$_']"
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다