无法解析XML并将节点作为属性进行访问

时间:2016-02-07 13:41:14

标签: xml parsing powershell

我有以下XML文件:

<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema
-design/2011">
  <Metadata>
    <Identity Language="en-US" Id="sample-extension" Version="0.1.0" Publisher="wouterdekortplayground"/>
    <DisplayName>Sample Extension</DisplayName>
    <Description xml:space="preserve">This is the extension file from the contributions guide example on GitHub.  Feel free to add or remove sections as y
ou see fit.</Description>
    <GalleryFlags/>
    <Tags>Sample</Tags>
    <Properties>
      <Property Id="Microsoft.VisualStudio.Services.Links.Home" Value="https://bit.ly"/>
      <Property Id="Microsoft.VisualStudio.Services.Links.Getstarted" Value="https://bit.ly"/>
      <Property Id="Microsoft.VisualStudio.Services.Links.Learn" Value="https://bit.ly"/>
      <Property Id="Microsoft.VisualStudio.Services.Links.Support" Value="https://bit.ly"/>
      <Property Id="Microsoft.VisualStudio.Services.Links.Repository" Value="https://bit.ly"/>
      <Property Id="Microsoft.VisualStudio.Services.Links.Issues" Value="https://bit.ly"/>
      <Property Id="Microsoft.VisualStudio.Services.Branding.Color" Value="#dcebfc"/>
      <Property Id="Microsoft.VisualStudio.Services.Branding.Theme" Value="light"/>
    </Properties>
    <Categories>Integrate</Categories>
    <Icon>img/logo.png</Icon>
  </Metadata>
  <Dependencies/>
  <Installation>
    <InstallationTarget Id="Microsoft.VisualStudio.Services"/>
  </Installation>
  <Assets>
    <Asset Type="Microsoft.VisualStudio.Services.Icons.Default" d:Source="File" Path="img/logo.png" Addressable="true"/>
    <Asset Type="img/logo.png" d:Source="File" Path="img/logo.png" Addressable="true"/>
    <Asset Type="css/app.css" d:Source="File" Path="css/app.css" Addressable="true"/>
    <Asset Type="css/jasmine.css" d:Source="File" Path="css/jasmine.css" Addressable="true"/>
    <Asset Type="scripts/app.d.ts" d:Source="File" Path="scripts/app.d.ts" Addressable="true"/>
    <Asset Type="scripts/app.js" d:Source="File" Path="scripts/app.js" Addressable="true"/>
    <Asset Type="scripts/app.js.map" d:Source="File" Path="scripts/app.js.map" Addressable="true"/>
    <Asset Type="scripts/app.ts" d:Source="File" Path="scripts/app.ts" Addressable="true"/>
    <Asset Type="scripts/Deploy.ps1" d:Source="File" Path="scripts/Deploy.ps1" Addressable="true"/>
    <Asset Type="scripts/jasmine-html.js" d:Source="File" Path="scripts/jasmine-html.js" Addressable="true"/>
    <Asset Type="scripts/jasmine.js" d:Source="File" Path="scripts/jasmine.js" Addressable="true"/>
    <Asset Type="scripts/VSS.SDK.js" d:Source="File" Path="scripts/VSS.SDK.js" Addressable="true"/>
    <Asset Type="index.html" d:Source="File" Path="index.html" Addressable="true"/>
    <Asset Type="Microsoft.VisualStudio.Services.Manifest" d:Source="File" Path="extension.vsomanifest" Addressable="true"/>
  </Assets>
</PackageManifest>

我尝试使用PowerShell修改此XML。我已经从ZIP存档中的文件中读取了文本。然后我将其转换为XML:

[CmdletBinding()]
param(
    [string] [Parameter(Mandatory=$true)] $PathToVSIX,
    [string] [Parameter(Mandatory=$true)] $Token,       
    [string] $BaseUrl
)

Set-StrictMode -Version 3
$VerbosePreference = "continue" 

$file = Get-ChildItem $PathToVSIX -Filter *.vsix -Recurse |
        % { $_.FullName } | Select -First 1
Write-Verbose "Found VSIX Package $file"

# Load ZipFile (Compression.FileSystem) if necessary
try { $null = [IO.Compression.ZipFile] }
catch { [System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') }

# Open zip file with update mode (Update, Read, Create -- are the options)
try { $fileZip = [System.IO.Compression.ZipFile]::Open( $file, 'Update' ) }
catch { throw "Another process has locked the '$file' file." }

$desiredFile = [System.IO.StreamReader]($fileZip.Entries | Where-Object { $_.FullName -match 'extension.vsixmanifest' }).Open()
$text = $desiredFile.ReadToEnd()
[xml]$xml = $text | ConvertTo-Xml 
$desiredFile.Close()
$desiredFile.Dispose()

一切似乎都没问题,但不知怎的,我无法访问PackageManifest或其他节点。

当我尝试访问$xml.PackageManifest时,我收到错误消息

  

该物业&#39; PackageManifest&#39;在这个对象上找不到。验证该属性是否存在。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

您的代码存在(至少)两个问题:

  • ConvertTo-Xml并没有像您认为的那样做。它用于将对象转换为XML表示,而不是将XML字符串解析为XML对象,因此结果不是您期望的结果:

    PS C:\> [xml]$xml = $text | ConvertTo-Xml
    PS C:\> $xml.Save([Console]::Out)
    <?xml version="1.0" encoding="ibm850"?>
    <Objects>
      <Object Type="System.String">&lt;?xml version="1.0" encoding="utf-8"?&gt;
    &lt;PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schem
    as.microsoft.com/developer/vsx-schema
    -design/2011"&gt;
      &lt;Metadata&gt;
        &lt;Identity Language="en-US" Id="sample-extension" Version="0.1.0" Publisher="wouterdekortplayground"/&gt;
        &lt;DisplayName&gt;Sample Extension&lt;/DisplayName&gt;
    ...

    从文档(强调我的):

      

    详细说明

         

    ConvertTo-Xml cmdlet 创建一个或多个Microsoft .NET Framework对象的基于XML的表示。 要使用此cmdlet,请将一个或多个对象传递给cmdlet,或使用InputObject参数指定对象。

    你首先不需要它。简单地将XML字符串转换为XML对象就足够了:

    [xml]$xml = $text
    
    PS C:\> [xml]$xml = $text
    PS C:\> $xml.Save([Console]::Out)
    <?xml version="1.0" encoding="ibm850"?>
    <PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.
    microsoft.com/developer/vsx-schema -design/2011">
      <Metadata>
        <Identity Language="en-US" Id="sample-extension" Version="0.1.0" Publisher="wouterdekortplayground" />
        <DisplayName>Sample Extension</DisplayName>
    ...
  • 您的XML数据使用名称空间:

    <PackageManifest Version="2.0.0"
      xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011"
      xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
    

    因此您需要namespace manager来选择节点:

    $nsm = New-Object Xml.XmlNamespaceManager($xml.NameTable)
    $nsm.AddNamespace('ns', $xml.DocumentElement.xmlns)
    $xml.SelectNodes('//ns:PackageManifest', $nsm)