как обновить файл xml с помощью xmlstarlet

Я использую версию xmlstarlet для Windows для обновления XML-файла через пакетный файл Windows.

xml edit --update "/xml/table/rec[@id=3]/@id" --value 10 %xmlfile%

Я ожидал, что это обновит атрибут id узла rec до 10. Когда я запускаю это, я вижу обновленный xml, как и ожидалось, в командной строке, но файл никогда не обновляется.

Как я могу это сделать, я не хочу переписывать весь файл, так как файл может быть большим.

перед обновлением:

<?xml version="1.0"?>
<xml>
  <table>
    <rec id="1" />
    <rec id="2" />
    <rec id="3" />
  </table>
</xml>

после обновления:

<?xml version="1.0"?>
<xml>
  <table>
    <rec id="1" />
    <rec id="2" />
    <rec id="10" />
  </table>
</xml>

person Schu    schedule 25.03.2015    source источник
comment
большинство инструментов оболочки не поддерживают обновление данных на месте. Например, опция sed -i (на месте) по-прежнему записывает данные в новое место на диске, а затем удаляет старый файл. Я думаю, то же самое верно и для инструментов XML. Я был бы очень удивлен, если бы xmlstarlet работал по-другому. Удачи.   -  person shellter    schedule 25.03.2015
comment
Покажите XML-документ до и после этого обновления.   -  person Mathias Müller    schedule 25.03.2015
comment
@Mathias Я, конечно, согласен с вами в принципе, что хорошо показывать ввод, но проблема здесь в редактировании на месте. Файла <xml><table><rec id="3"/></table></xml> достаточно, чтобы воспроизвести проблему — атрибут id изменен, но вывод выводится на стандартный вывод, а не обратно в файл.   -  person Tom Fenech    schedule 25.03.2015
comment
@TomFenech Я также согласен с вами, но иногда OP не дает надежной или полной информации о том, что происходит - например, XML-документ может быть неправильно сформирован, но они не упомянули об этом.   -  person Mathias Müller    schedule 25.03.2015


Ответы (1)


Вы не показали свой входной документ, но я предполагаю, что он следующий, взятый из документации xmlstarlet :

<xml>
  <table>
    <rec id="1">
      <numField>123</numField>
      <stringField>String Value</stringField>
    </rec>
    <rec id="2">
      <numField>346</numField>
      <stringField>Text Value</stringField>
    </rec>
    <rec id="3">
      <numField>-23</numField>
      <stringField>stringValue</stringField>
    </rec>
  </table>
</xml>

xmlstarlet изменяет файл, но результат отправляется на стандартный вывод, а не сохраняется в исходном файле. Используйте другую опцию --inplace, чтобы изменить файл на месте:

$ xml ed --inplace -u "/xml/table/rec[@id='3']/@id" -v 5 rec.xml

Затем:

$ cat rec.xml
<?xml version="1.0"?>
<xml>
  <table>
    <rec id="1">
      <numField>123</numField>
      <stringField>String Value</stringField>
    </rec>
    <rec id="2">
      <numField>346</numField>
      <stringField>Text Value</stringField>
    </rec>
    <rec id="5">
      <numField>-23</numField>
      <stringField>stringValue</stringField>
    </rec>
  </table>
</xml>

Кстати, этот вопрос, кажется, задает что-то очень похожее на этот вопрос.


РЕДАКТИРОВАНИЕ: по предложению @npostavs этот параметр указан в справке по редактированию:

$ xml edit --help
...
-L (or --inplace)   - edit file inplace
...
person Mathias Müller    schedule 25.03.2015
comment
большое спасибо, матиас. это помогло. Я искал эту опцию и нигде не мог найти ее в API. как ты нашел этот? - person Schu; 25.03.2015
comment
@Schu На мой взгляд, это действительно не часть документации. Ноам Поставски кратко упоминает, что он не поставлялся с первоначальным выпуском. - person Mathias Müller; 26.03.2015
comment
Осторожнее с пространствами имен. В моем файле было определено пространство имен, и мне пришлось добавлять _: перед каждым элементом, как определено в документах в разделе 1.3. A More Convenient Solution - person LeoLozes; 08.09.2017
comment
@LeoLozes Да, если в вашем документе есть пространства имен, вы должны позаботиться о них. Но у документа в вопросе нет пространств имен, поэтому в этом нет необходимости. - person Mathias Müller; 12.09.2017
comment
спасибо .. мне очень помогает эта опция xmlstarlet на месте. - person eigenfield; 19.10.2017
comment
Отличный комментарий! Эта опция --inplace отсутствует в документах... - person user2403232; 04.12.2020