[英]XSL Complex Transform from PowerShell Output
我仍在學習 XSL 和 XML 模式,但不幸的是,我遇到了來自 PowerShell 導出的相當復雜的輸出,我需要將其轉換為 Access 的可讀格式。
不幸的是,拋出了一些相當復雜的東西,按照我能夠抓取的指導,我試圖對其進行排序的努力都白費了:
<Obj RefId="0">
<TN RefId="0">
<T>System.IO.DirectoryInfo</T>
<T>System.IO.FileSystemInfo</T>
<T>System.MarshalByRefObject</T>
<T>System.Object</T>
</TN>
<ToString>Archive Files - Requested</ToString>
<Props>
<S N="Name">Archive Files - Requested</S>
<Obj N="Parent" RefId="1">
<TNRef RefId="0" />
<ToString>Archive Files</ToString>
<Props>
<S N="Name">Archive Files</S>
<S N="Parent"></S>
<B N="Exists">true</B>
<S N="Root">N:\</S>
<S N="FullName">N:\Archive Files</S>
<S N="Extension"></S>
<DT N="CreationTime">2016-02-24T08:23:01.3111895+00:00</DT>
<DT N="CreationTimeUtc">2016-02-24T08:23:01.3111895Z</DT>
<DT N="LastAccessTime">2019-09-19T03:00:01.2502407+01:00</DT>
<DT N="LastAccessTimeUtc">2019-09-19T02:00:01.2502407Z</DT>
<DT N="LastWriteTime">2016-02-24T08:25:10.3301992+00:00</DT>
<DT N="LastWriteTimeUtc">2016-02-24T08:25:10.3301992Z</DT>
<S N="Attributes">Directory</S>
</Props>
<MS>
<S N="BaseName">Archive Files</S>
<S N="Mode">d----</S>
</MS>
</Obj>
理想情況下,我想讓事情變得平坦,並讓它看起來像:
<Root>
<Record>
<RefID>#</RefID>
<Name>Archive Files</Name>
<Parent></Parent>
<FullName>N:\Archive Files</FullName>
<Extension></Extension>
<CreationTime>2016-02-24T08:23:01.3111895+00:00</Creationtime>
<LastAccessTime>2019-09-19T03:00:01.2502407+01:00</LastAccessTime>
<LastWriteTime">2016-02-24T08:25:10.3301992+00:00</LastWriteTime>
<Attributes>Directory</Attributes>
<BaseName>Archive Files</BaseName>
<Mode>d----</Mode>
</Record>
</Root>
您帖子中的示例 XML 看起來非常像CliXml
——PowerShell 的內部序列化格式。
您可以使用Import-CliXml
反序列化對象:
# Import from CliXml
$directoryData = Import-CliXml -Path .\path\to\input.xml
# Export to a format Access can consume
$directoryData |Export-Csv .\path\to\output.csv -NoTypeInformation
如果我理解正確,您有一個 xml 文件,您想將其轉換為另一個(不太復雜的)xml。
使用您的示例(並更正結束標記),您可以執行以下操作:
$recordTemplate = @"
<Record>
<RefID>{0}</RefID>
<Name>{1}</Name>
<Parent>{2}</Parent>
<FullName>{3}</FullName>
<Extension>{4}</Extension>
<CreationTime>{5}</CreationTime>
<LastAccessTime>{6}</LastAccessTime>
<LastWriteTime>{7}</LastWriteTime>
<Attributes>{8}</Attributes>
<BaseName>{9}</BaseName>
<Mode>{10}</Mode>
</Record>
"@
[xml]$xml = Get-Content -Path 'D:\test\complex.xml' -Raw
$records = foreach ($item in $xml.Obj.Props.Obj) {
# create a Hashtable for the 'S' elements
$sHash = @{}
$item.Props.S | ForEach-Object { $sHash[$_.N] = $_.'#text' }
# create a Hashtable for the 'DT' elements
$dtHash = @{}
$item.Props.DT | ForEach-Object { $dtHash[$_.N] = $_.'#text' }
# get the two values from the MS element
# (you could also do this with a hashtable of course..)
$baseName = ($item.MS.S | Where-Object { $_.N -eq 'BaseName' }).'#text'
$mode = ($item.MS.S | Where-Object { $_.N -eq 'Mode' }).'#text'
# output a Record node using the template
$recordTemplate -f $item.RefId, $sHash.Name, $sHash.Parent,
$sHash.FullName, $sHash.Extension,
$dtHash.CreationTime, $dtHash.LastAccessTime,
$dtHash.LastWriteTime, $sHash.Attributes,
$baseName, $mode
}
# create the full XML as string
$newXml = @"
<?xml version="1.0" encoding="utf-8"?>
<Root>
$($records -join [environment]::NewLine)
</Root>
"@
# save the xml string to disk
$newXml | Set-Content -Path 'D:\test\readable.xml' -Encoding Utf8
輸出:
<?xml version="1.0" encoding="utf-8"?>
<Root>
<Record>
<RefID>1</RefID>
<Name>Archive Files</Name>
<Parent></Parent>
<FullName>N:\Archive Files</FullName>
<Extension></Extension>
<CreationTime>2016-02-24T08:23:01.3111895+00:00</CreationTime>
<LastAccessTime>2019-09-19T03:00:01.2502407+01:00</LastAccessTime>
<LastWriteTime>2016-02-24T08:25:10.3301992+00:00</LastWriteTime>
<Attributes>Directory</Attributes>
<BaseName>Archive Files</BaseName>
<Mode>d----</Mode>
</Record>
</Root>
在 XSLT 中,您可以使用模板規則完成大部分工作:
<xsl:template match="*[@N]">
<xsl:element name="{@N}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
這是我認為有點棘手的唯一部分,所以剩下的就交給你了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.