Powershell获取错误无法将值“System.Xml.XPathNodeList”转换为“System.Xml.XmlDocument”类型

时间:2017-07-05 07:20:33

标签: xml powershell

我有以下的powershell代码,它选择了一个具有命名空间的xml节点。

$ns = new-Object System.Xml.XmlNamespaceManager $doc.NameTable
$ns.AddNamespace("dns", "http://www.nlog-project.org/schemas/NLog.xsd")
$obj3 = $doc.SelectNodes('//dns:nlog',$ns)

但我收到以下错误:

  

无法将值“System.Xml.XPathNodeList”转换为类型   “System.Xml.XmlDocument”。错误:“指定的节点不能   作为此节点的有效子项插入,因为指定的节点   是错误的类型。“在   C:\ MetacubeAutoBuildDeployment \ PowershellScripts \ PEStandAloneWebConfigReplace.ps1:15   焦炭:1   + $ obj3 = $ doc.SelectNodes('// dns:nlog',$ ns)   + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~       + CategoryInfo:MetadataError:(:) [],ArgumentTransformationMetadataException       + FullyQualifiedErrorId:RuntimeException

此错误有什么具体原因吗? 我必须获取$ doc中突出显示的connectionString标记的值。 $ doc包含:

<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
    <section name="ciel" type="Ciel.Application.Common.CielConfigSectionHandler, Ciel.Application" />
    <sectionGroup name="elmah">
      <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
      <section name="errorLog" requirePermission="false" type="Elmah.FallbackErrorLogSectionHandler, Elmah.FallbackErrorLog" />
      <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
      <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
    </sectionGroup>
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <!-- Load NLog extensions from the *.dll file -->
    <extensions>
      <add assembly="NLog.Web" />
      <add assembly="NLog.Extended" />
    </extensions>
    <!-- Targets or Output -->
    <targets>
      <default-wrapper xsi:type="AsyncWrapper" />
      <!-- File Target -->
      <target name="sqllog" xsi:type="File" fileName="App_Data/NLoggerLogs/PESql.log" archiveFileName="App_Data/log/CielSql.{#####}.log" maxArchiveFiles="100" archiveAboveSize="10485760" archiveNumbering="Sequence" concurrentWrites="true" keepFileOpen="false" encoding="UTF-8">
        <layout xsi:type="CSVLayout" delimiter="Tab">
          <column name="level" layout="${level:uppercase=true}" />
          <column name="aspnet-sessionid" layout="${aspnet-sessionid}" />
          <column name="aspnet-request(ASP.NET_SessionId)" layout="${aspnet-request:cookie=ASP.NET_SessionId}" />
          <column name="aspnet-request(HTTP_USER_AGENT)" layout="${aspnet-request:serverVariable=HTTP_USER_AGENT}" />
          <column name="aspnet-request(REMOTE_ADDR)" layout="${aspnet-request:serverVariable=REMOTE_ADDR}" />
          <column name="aspnet-request(REMOTE_HOST)" layout="${aspnet-request:serverVariable=REMOTE_HOST}" />
          <column name="date" layout="${longdate}" />
          <column name="message" layout="${message:exceptionSeparator=|:withException=true}" />
          <column name="aspnet-user-identity" layout="${aspnet-user-identity}" />
        </layout>
      </target>
      <target name="debuglog" xsi:type="File" fileName="App_Data/NLoggerLogs/PE.log" archiveFileName="App_Data/log/Ciel.{#####}.log" maxArchiveFiles="100" archiveAboveSize="2097152" archiveNumbering="Sequence" concurrentWrites="true" keepFileOpen="false" encoding="UTF-8">
        <layout xsi:type="CSVLayout" delimiter="Tab">
          <column name="date" layout="${longdate}" />
          <column name="level" layout="${level:uppercase=true}" />
          <column name="asp-application" layout="${asp-application}" />
          <column name="asp-request" layout="${asp-request:cookie=String:serverVariable=String:queryString=String:item=String:form=String}" />
          <column name="asp-session" layout="${asp-session:variable=String}" />
          <column name="aspnet-sessionid" layout="${aspnet-sessionid}" />
          <column name="aspnet-session" layout="${aspnet-session:variable=Sring}" />
          <column name="aspnet-application" layout="${aspnet-application:variable=String}" />
          <column name="aspnet-request" layout="${aspnet-request:cookie=String:serverVariable=String:queryString=String:item=String:form=String}" />
          <column name="aspnet-request(ASP.NET_SessionId)" layout="${aspnet-request:cookie=ASP.NET_SessionId}" />
          <column name="aspnet-request(HTTP_USER_AGENT)" layout="${aspnet-request:serverVariable=HTTP_USER_AGENT}" />
          <column name="aspnet-request(URL)" layout="${aspnet-request:serverVariable=URL}" />
          <column name="aspnet-request(REMOTE_ADDR)" layout="${aspnet-request:serverVariable=REMOTE_ADDR}" />
          <column name="aspnet-request(REMOTE_HOST)" layout="${aspnet-request:serverVariable=REMOTE_HOST}" />
          <column name="aspnet-user-authtype" layout="${aspnet-user-authtype}" />
          <column name="aspnet-user-identity" layout="${aspnet-user-identity}" />
          <column name="threadid" layout="${threadid}" />
          <column name="stacktrace" layout="${stacktrace:topFrames=2}" />
          <column name="machinename" layout="${machinename}" />
          <column name="document-uri" layout="${document-uri}" />
          <column name="callsite" layout="${callsite:className=true:fileName=true:includeSourcePath=true:methodName=true}" />
          <column name="message" layout="${message:exceptionSeparator=|:withException=true}" />
        </layout>
      </target>
      <target name="accesslog" xsi:type="File" fileName="${basedir}/APP_Data/NLoggerLogs/PEAccess.log" archiveFileName="${basedir}/App_Data/log/CielAccess.{#####}.log" maxArchiveFiles="100" archiveAboveSize="2097152" archiveNumbering="Sequence" concurrentWrites="true" keepFileOpen="false" encoding="UTF-8">
        <layout xsi:type="CSVLayout" delimiter="Tab">
          <column name="aspnet-sessionid" layout="${aspnet-sessionid}" />
          <column name="aspnet-request(HTTP_USER_AGENT)" layout="${aspnet-request:serverVariable=HTTP_USER_AGENT}" />
          <column name="aspnet-request(REMOTE_ADDR)" layout="${aspnet-request:serverVariable=REMOTE_ADDR}" />
          <column name="aspnet-request(REMOTE_HOST)" layout="${aspnet-request:serverVariable=REMOTE_HOST}" />
          <column name="date" layout="${longdate}" />
          <column name="message" layout="${message:exceptionSeparator=|:withException=true}" />
        </layout>
      </target>
      <target name="database" xsi:type="Database">
        <!--
        Remarks:
          The appsetting layouts require the NLog.Extended assembly.
          The aspnet-* layouts require the NLog.Web assembly.
          The Application value is determined by an AppName appSetting in Web.config.
          The "NLogDb" connection string determines the database that NLog write to.
          The create dbo.Log script in the comment below must be manually executed.
        -->
        <!--<connectionStringName>SQLServer_develop</connectionStringName>-->
        <dbProvider>System.Data.SqlClient</dbProvider>
        **<connectionString>server=server;database=database;integrated security=False;User ID=userid;Password=password</connectionString>**
        <commandText>
          insert into [CIEL].[DPR_JOBINSTANCEDETAILS] (
          JOBID, JOBINSTANCEID, STEPINSTANCEID,STEPID,LOGTYPE, MESSAGETYPE, MESSAGE, PARENTID,LOGGEDON
          )
          values (
          @JOBID, @JOBINSTANCEID, @STEPINSTANCEID, @STEPID, @LOGTYPE,@MESSAGETYPE, @MESSAGE, @PARENTID, @LOGGEDON
          );
        </commandText>
        <parameter name="@JOBID" layout="${event-properties:item=JOBID}" />
        <parameter name="@JOBINSTANCEID" layout="${event-properties:item=JOBINSTANCEID}" />
        <parameter name="@STEPINSTANCEID" layout="${event-properties:item=STEPINSTANCEID}" />
        <parameter name="@STEPID" layout="${event-properties:item=STEPID}" />
        <parameter name="@LOGTYPE" layout="${event-properties:item=LOGTYPE}" />
        <parameter name="@MESSAGETYPE" layout="${event-properties:item=MESSAGETYPE}" />
        <parameter name="@MESSAGE" layout="${event-properties:item=MESSAGE}" />
        <parameter name="@PARENTID" layout="${event-properties:item=PARENTID}" />
        <parameter name="@LOGGEDON" layout="${date}" />
      </target>
      <target name="sqllog_table" xsi:type="Database">
        <!--Remarks:
          The appsetting layouts require the NLog.Extended assembly.
          The aspnet-* layouts require the NLog.Web assembly.
          The Application value is determined by an AppName appSetting in Web.config.
          The "NLogDb" connection string determines the database that NLog write to.
          The create dbo.Log script in the comment below must be manually executed.-->
        <connectionStringName>NLogConnection</connectionStringName>
      </target>
    </targets>
    <!-- Rules for calling the appropriate Target -->
    <rules>
      <logger name="DebugLogger" minlevel="Debug" writeTo="debuglog" />
      <logger name="SqlLogger" minlevel="Debug" writeTo="sqllog" />
      <logger name="AccessLogger" minlevel="Info" writeTo="accesslog" />
      <logger name="PROCESSENGINEDB" minlevel="Trace" writeTo="database" />
    </rules>
  </nlog>
</configuration>

1 个答案:

答案 0 :(得分:1)

您可以按WOxxOm's comments的建议使用GetElementsByTagName。它很优雅。但是潜在的问题可能是由更改xml结构,重新排序或多个connectionStrings引起的。

您可以对XML进行点索引。优点是它更明确。缺点是它更明确。

如果您更改connectionString的路径,则需要更新GetElementsByTagName不会更新的路径。但是,这对于明确定义您感兴趣的标记更方便,并且可以方便地访问该标记中的其他信息。我发现它通常更直观。

$dbdetails = $doc.configuration.nlog.targets.target | Where-Object {$_.name -eq "database"}
$dbdetails.ConnectionString

您的代码在PowerShell v5.1上没有给我同样的错误。我复制了$ doc的代码,使用here-string将其分配给变量:

[xml]$doc = @"
    ...
"@

修改

两全其美?

$dbdetails = $doc.GetElementsByTagName("target") | Where-Object {$_.name -eq "database"}

Get-Member ,显示可访问的属性

Get-Member n $dbdetails