Как остановить вывод, разделенный пустыми строками, с помощью xmllint
У меня есть следующий XML-файл, созданный из Gnote:
<?xml version="1.0"?>
<note version="0.3" xmlns:link="http://beatniksoftware.com/tomboy/link" xmlns:size="http://beatniksoftware.com/tomboy/size" xmlns="http://beatniksoftware.com/tomboy"><title>things</title><text xml:space="preserve"><note-content version="0.1" xmlns:link="http://beatniksoftware.com/tomboy/link" xmlns:size="http://beatniksoftware.com/tomboy/size">things
<list><list-item dir="ltr">sheets
</list-item><list-item dir="ltr">test
</list-item><list-item dir="ltr">eval</list-item></list>
asd
</note-content>
</text><last-change-date>2023-02-19T12:20:06.551763Z</last-change-date><last-metadata-change-date>2023-02-19T12:20:06.553010Z</last-metadata-change-date><create-date>2023-02-19T10:40:01.309068Z</create-date><cursor-position>90</cursor-position><selection-bound-position>-1</selection-bound-position><width>649</width><height>282</height></note>
Я хочу, чтобы весь текстовый контент был в<note-content></note-content>
без дополнительных символов новой строки. Сюда входит текстовое содержимое в элементах списка/элемента списка. Запрошенное содержимое следующее, включая формат:
things
sheets
test
eval
asd
После долгих проб и ошибок анализ XML с помощьюxmllint --xpath "//*[local-name()='note']/*[local-name()='text']/*[local-name()='note-content']/text() | //*[local-name()='note']/*[local-name()='text']/*[local-name()='note-content']/*[local-name()='list']/*[local-name()='list-item'][@dir='ltr']/text()[normalize-space()]" a.xml
(с или без--noblanks
) выдает выходные данные, разделенные дополнительными символами новой строки/пустыми строками (после этого должна быть пустая строка).asd
но блок кода этого не показывает):
things
sheets
test
eval
asd
Удаление новых строк в файле xml и использование той же команды xmllint выводит желаемый результат без дополнительных символов новой строки/пустых строк, поэтому я не знаю, создает ли Gnote что-то нестандартное.
Я пытался просмотреть комментарии и ответы на https://stackoverflow.com/questions/11776910/xpath-expression-to-remove-whitespace/11777638, но мне это не удалось. Некоторые наблюдения:
- Когда я попытался выполнить (обратите внимание на
|
)xmllint --xpath "normalize-space(//*[local-name()='note']/*[local-name()='text']/*[local-name()='note-content']/text()) | normalize-space(//*[local-name()='note']/*[local-name()='text']/*[local-name()='note-content']/*[local-name()='list']/*[local-name()='list-item'][@dir='ltr']/text())" a.xml
Я получил:
Ошибка XPath: неверный тип.
Ошибка оценки XPath
- Даже если я переработал свой сценарий для выполнения нескольких вызовов xmllint, у меня осталась одна строка, в которой удалены символы новой строки, и это хорошо, но какую строку необходимо заранее установить вручную. Так, например, здесь представлены варианты Normalize-space и Translate(normalize-space, ' ', '') для пути к элементу note-content:
xmllint --xpath "normalize-space(//*[local-name()='note']/*[local-name()='text']/*[local-name()='note-content']/text())" a.xml xmllint --xpath "translate(normalize-space(//*[local-name()='note']/*[local-name()='text']/*[local-name()='note-content']/text()), ' ', '')" a.xml
Оба возвращают один из двух элементов в элементе note-content без символов новой строки ([1] — это вещи, а [2] — это asd). Я могу выбирать между ними, добавляя [1] или [2] к text(), но это не работает, если у меня неопределенное количество элементов. (Я не знаю, есть ли способ просто получить таким образом весь текстовый массив/элементы). - Некоторые ответы предлагают использовать
[normalize-space() = 'desiredtext']
, это не сработает, если я не могу ожидать текст в сгенерированном XML. - Если у меня просто есть
[normalize-space()]
после :xmllint --noblanks --xpath "//*[local-name()='note']/*[local-name()='text']/*[local-name()='note-content']/text()[normalize-space()] | //*[local-name()='note']/*[local-name()='text']/*[local-name()='note-content']/*[local-name()='list']/*[local-name()='list-item'][@dir='ltr']/text()[normalize-space()]" a.xml
У меня остался тот же результат, с которого я начал. - Я попробовал добавить
[not(.='')]
послеtext()
Я получаю тот же результат.
Вопрос: я хочу знать, вызвано ли это чрезмерное поведение пустых строк неправильными командами xmllint/xpath или тем, как Gnote сгенерировал xml и правильные команды xmllint/xpath, если таковые имеются. Я не собираюсь использовать xmlstarlet, потому что, похоже, он больше не поддерживается. Этот вопрос не требует способа передать это в команду, которая удаляет лишние символы новой строки.
1 ответ
Хотя вы выразили предпочтение избегатьxmlstarlet
, он сделает именно то, что вы хотите:
xmlstarlet sel -t -v '//_:note-content' -n xmlfile
Выход
Используя I не могу избежать пустых строк, которые являются частью текста значения элемента:
xmllint --xpath '//*[local-name()="note-content"]//text()' xmlfile
Выход
things
sheets
test
eval
asd
Проведя некоторое время сxmllint
Я бы посоветовал вам просто удалить пустые строки. (Не идеально, но, безусловно, эффективно.)
xmllint … | grep .
Выход
things
sheets
test
eval
asd