Как избавиться от невозможности установить значение для типа узла «документ» в XML? - PullRequest
0 голосов
/ 01 мая 2018

Я не уверен, где 'я иду здесь не так. У меня следующее сообщение об ошибке 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 голосов
/ 02 мая 2018

Нужно было создать образец 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);
0 голосов
/ 02 мая 2018

Существенно 3 проблемы с вашим кодом:

  1. $XMLDoc.SelectNodes() возвращает коллекцию узлов. Вы не можете использовать это в операторе точки доступа ($XMLDoc.$controlSource), и вам все равно это не нужно. Просто опустите $XMLDoc. и зациклите элементы коллекции.

  2. Ваше выражение XPath выбирает value узлов атрибутов. Однако вы не можете присвоить значение непосредственно узлу. Вы должны присвоить его свойству Value или #text. Обратите внимание, что в отличие от Value свойство #text принимает только значения типа string.

  3. Значение, которое вы хотите присвоить, является строкой в ​​одинарных кавычках, поэтому PowerShell не будет расширять в ней переменную $replaceText. Удалить одинарные кавычки.

Это будет делать то, что вы хотите:

$xpath = "/beans/bean[@id='$bNode']/property[@name='MapOverride']/map/entry[@key='node.infoblock']/@value"
$XMLDoc.SelectNodes($xpath) | ForEach-Object {
    $_.Value = $replaceText
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...