我怎样才能过去无法在XML中的“文档”节点类型上设置值?

时间:2018-05-01 17:54:33

标签: xml powershell

我不确定我在哪里出错了。我有以下PowerShell错误消息:

Exception setting "Value": "Cannot set a value on node type
'Document'." At line:18 char:5
+     $XMLDoc.$controlSource='$replaceText'
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : CatchFromBaseAdapterSetValue

我的代码如下:

[xml]$XMLDoc = (Get-Content "C:\process.xml")

foreach($file in Get-ChildItem $outputDirectory) {
    $replaceText = <tested working string of the value to replace in the XML doc>
    $controlSource = $XMLDoc.SelectNodes("/beans/bean[@id='$bNode']/property[@name='configOverrideMap']/map/entry[@key='sfdc.extractionSOQL']/@value")

    $XMLDoc.$controlSource = '$replaceText'

    #$XMLDoc -replace ('^"$controlSource"$','^"$replaceText"$') | Out-File $XMLDoc
}

我正在尝试用字符串替换XML文件中的值,并将变量$XMLDoc的内容写入文件C:\process.xml,直到我收到上述消息。我可以得到关于将$XMLDoc写入文件的部分,问题是我仍然无法获取我的字符串来替换变量并保存。我理解这可能很草率,因为我在foreach循环中多次执行相同的任务,但我目前的目标是功能而不是最佳功能。

<beans>
  <bean id="MenuGet">
    <property name="name" />
    <property name="MapOverride">
      <map>
        <entry key="node.infoblock" value="k4jk2jb54B$T45bt2j5ktb3B%$" />
      </map>
    </property>
  </bean>
  <bean id="SystemGet">
    <property name="name" />
    <property name="MapOverride">
      <map>
        <entry key="node.infoblock" value="b34t34bhj54b%B#Y$%Bn45ht5h" />
      </map>
    </property>
  </bean>
</beans>

2 个答案:

答案 0 :(得分:1)

您的代码存在3个问题:

  1. $XMLDoc.SelectNodes()返回节点集合。您不能在点访问语句($XMLDoc.$controlSource)中使用它,并且您无论如何都不需要。只需删除$XMLDoc.并循环遍历集合的元素。

  2. 您的XPath表达式选择value个属性节点。但是,您无法直接为节点分配值。您必须将其分配给其Value#text媒体资源。请注意,与Value不同,属性#text仅接受string类型的值。

  3. 您要分配的值是单引号字符串,因此PowerShell不会在其中展开变量$replaceText。删除单引号。

  4. 这将做你想要的:

    $xpath = "/beans/bean[@id='$bNode']/property[@name='MapOverride']/map/entry[@key='node.infoblock']/@value"
    $XMLDoc.SelectNodes($xpath) | ForEach-Object {
        $_.Value = $replaceText
    }
    

答案 1 :(得分:1)

必须创建与问题中的示例XML略有不同的示例XML,以获得基于XPath的简短工作示例:

[xml]$XMLDoc= @'
<beans>
  <bean id="MenuGet">
    <property name="name" />
    <property name="MapOverride">
      <map>
        <entry key="node.infoblock" value="k4jk2jb54B$T45bt2j5ktb3B%$" />
      </map>
    </property>
  </bean>
  <bean id="SystemGet">
    <property name="name" />
    <property name="MapOverride">
      <map>
        <entry key="node.infoblock" value="b34t34bhj54b%B#Y$%Bn45ht5h" />
      </map>
    </property>
  </bean>
</beans>
'@;

一些简单的替换数据来模仿foreach循环:

$replacements = @{
    MenuGet = 'MenuGet-REPLACE';
    SystemGet = 'SystemGet-REPLACE';
};

这里有一些测试/工作示例代码:

foreach($bNode in $replacements.Keys)
{
    $replaceText= $replacements.$bNode;
    $controlSource = $XMLDoc.SelectSingleNode(
        "/beans/bean[@id='$bNode']/property[@name='MapOverride']/map/entry[@key='node.infoblock']/@value"
    );

    $controlSource.Value = $replaceText;
}  
$XMLDoc.OuterXml;
# $XMLDoc.Save($OUT_PATH);