簡體   English   中英

來自 PowerShell 輸出的 XSL 復雜轉換

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM