Найти-заменить в иерархии файлов XML
У меня есть около 350 файлов XML, распределенных по всему /abc
каталог. Я хотел бы найти все случаи, когда значение атрибута alt в точности равно "бла-бла":
<image alt="blah blah" src="../webcontent/filename.png">
<caption>
Figure 1.1: Typical Components of Blah Blah
</caption>
</image>
и заменить значение alt
атрибут с содержимым, заключенным в caption
(удаление новых строк)
<image alt="Figure 1.1: Typical Components of Blah Blah" src="../webcontent/filename.png">
<caption>
Figure 1.1: Typical Components of Blah Blah
</caption>
</image>
Я открыт для запуска сценария в Ubuntu или Windows или использования любого инструмента для редактирования текста.
Не безопасно предполагать, что переводы строки и отступы совпадают. Кроме того, не все изображения имеют подписи. Все XML-документы в пути правильно сформированы.
Есть ли простой способ сценария этой замены на месте? Я был бы открыт для чего-то, что работает для одного файла; Я могу расширить его, чтобы запустить рекурсивно.
2 ответа
Для одного файла, следующая таблица стилей XSLT сделает эту работу:
<t:transform version="1.0" xmlns:t="http://www.w3.org/1999/XSL/Transform">
<t:template match="node()|@*">
<t:copy>
<t:apply-templates select="node()|@*"/>
</t:copy>
</t:template>
<t:template match="image/@alt[. = 'blah blah']">
<t:attribute name="alt" select="normalize-space(../caption)"/>
</t:template>
</t:transform>
Для обработки нескольких файлов вы можете вызывать таблицу стилей несколько раз из какого-либо сценария оболочки, сценария Ant или аналогичного (или посмотрите на xmlsh), или, если вы используете процессор XSLT 2.0, такой как Saxon, вы можете создать сценарий внутри самого XSLT. используя функцию collection()
Вы также можете использовать xmlstarlet
:
xmlstarlet ed -u '//image/@alt[.= "blah blah"]' -x "normalize-space(../caption/text())"