Как использовать XMLStarlet / Xpath для выделения текста внутри , но исключить некоторые внутренние

#xml #xpath #text #xmlstarlet

#xml #xpath #текст #xmlstarlet

Вопрос:

У меня есть такие html-файлы. В основном он содержит div, содержащий тексты с одним внутренним диапазоном, а остальная текстовая часть имеет довольно произвольный формат.

 <html>
<div>
<span class="c1">Text1</span><br/>
Text4<br/>
Text5
</div>
<div>
<span class="c1">TextA</span><a href="...">TextD</a>
</div>
</html>
 

тривиально выбирать / печатать только определенный текст внутри span с
xml sel -t -m "/html/div" -v "span[@class='c1']" -n

Однако я не знаю, как выбрать / распечатать остальной текст внутри, но за пределами диапазона, независимо от любых других тегов, таких как <br/> . Функция text() работает не так, как я ожидал.

xml sel -t -m "/html/div" -v "concat(span[@class='c1'],'|',text(),'$')" -n будет вырезать текст за <br/> тегами.

как я могу получить что-то вроде

 Text1|
Text4
Text5$
TextA|TextD$

 

Ответ №1:

Прошло некоторое время, но вы сказали,

Я хотел бы знать, есть ли лучший способ, чем метод substr

Вот версия, которая выдает вывод в порядке документа, используя шаблон, соответствующий объединению желаемых элементов внутри /html/div . Другие элементы, чем br выводятся с их текстовым значением, за которым следует вертикальная полоса. Каждый br элемент выводится с новой строкой и последующим br нормализованным текстом. Наконец, после 2 -b секунд, нарушающих -m вложенность, каждый div заканчивается знаком доллара, за которым следует новая строка.

 xmlstarlet sel -T -t 
-m "/html/div" 
  -m 'a | br | span[@class="c1"]' 
  --if 'local-name() = "br"' 
       -n -v 'normalize-space(following-sibling::text())' 
  --else -v '.' -o '|' 
  -b -b -o '

Вывод:

 Text1|
Text4
Text5$
TextA|TextD|$
 

Чтобы удалить последнее | перед $ заменой -o '|' на
-v 'substring("|",1,count(following-sibling::*))'
который выдается | только в том случае, если есть больше родственных элементов.

Чтобы добавить поддержку p элементов, например, добавьте | p ко 2-му -m выражению и добавьте <p>Hello from P</p> /html/div в исходный файл.

(Документация --if … --elif … --else … , э-э, менее чем обильная, но, насколько я могу понять, из кода XSLT, выводимого с помощью -C опции, --if предложение завершается -b .)

Я использовал xmlstarlet 1.6.1.

Ответ №2:

Я протестировал некоторые xpath, поэтому лучший, который я нашел, это

 //div/descendant-or-self::*/text()[normalize-space()]
 

результат xpath

Он указывает на контекстный узел и всех его потомков, получает текстовые значения, которые не являются пустыми.

об оси XPath

Ответ №3:

Я думаю, что есть лучший способ выполнить эту работу, но у меня есть этот. Я протестировал его в scrapy xpath.Я думаю, это поможет вам.

 print(data.xpath("concat(string(//div[1]/span[contains(@class, 'c1')]),'|', 'n',substring-before(substring-after(//div[1], 'Text1'), 'Text5'),'n',substring-after(substring-after(//div[1], 'Text1'),'Text4'),'

вывод:

 Text1|
Text4
Text5$
TextA|TextD$
 

Комментарии:

1. Я хотел бы найти общий способ. Text1 и так далее - это просто случайный пример.

Ответ №4:

Каким-то образом я нашел решение с substring-after

 xml sel -t  -m "/html/div" -v "span[@class='c1']" -o '|' -v "substring-after(.,span[@class='c1'])" -n
 

но я хотел бы знать, есть ли лучший способ, чем метод substr .

-n
source
Вывод:


Чтобы удалить последнее | перед $ заменой -o '|' на
-v 'substring("|",1,count(following-sibling::*))'
который выдается | только в том случае, если есть больше родственных элементов.

Чтобы добавить поддержку p элементов, например, добавьте | p ко 2-му -m выражению и добавьте <p>Hello from P</p> /html/div в исходный файл.

(Документация --if … --elif … --else … , э-э, менее чем обильная, но, насколько я могу понять, из кода XSLT, выводимого с помощью -C опции, --if предложение завершается -b .)

Я использовал xmlstarlet 1.6.1.

Ответ №2:

Я протестировал некоторые xpath, поэтому лучший, который я нашел, это


результат xpath

Он указывает на контекстный узел и всех его потомков, получает текстовые значения, которые не являются пустыми.

об оси XPath

Ответ №3:

Я думаю, что есть лучший способ выполнить эту работу, но у меня есть этот. Я протестировал его в scrapy xpath.Я думаю, это поможет вам.


вывод:


Комментарии:

1. Я хотел бы найти общий способ. Text1 и так далее - это просто случайный пример.

Ответ №4:

Каким-то образом я нашел решение с substring-after


но я хотел бы знать, есть ли лучший способ, чем метод substr .

, 'n',//div[2]/span[contains(@class, 'c1')]/text(),'|',//div[2]/a/text(),'

вывод:


Комментарии:

1. Я хотел бы найти общий способ. Text1 и так далее - это просто случайный пример.

Ответ №4:

Каким-то образом я нашел решение с substring-after


но я хотел бы знать, есть ли лучший способ, чем метод substr .

-n
source

Вывод:


Чтобы удалить последнее | перед $ заменой -o '|' на
-v 'substring("|",1,count(following-sibling::*))'
который выдается | только в том случае, если есть больше родственных элементов.

Чтобы добавить поддержку p элементов, например, добавьте | p ко 2-му -m выражению и добавьте <p>Hello from P</p> /html/div в исходный файл.

(Документация --if … --elif … --else … , э-э, менее чем обильная, но, насколько я могу понять, из кода XSLT, выводимого с помощью -C опции, --if предложение завершается -b .)

Я использовал xmlstarlet 1.6.1.

Ответ №2:

Я протестировал некоторые xpath, поэтому лучший, который я нашел, это


результат xpath

Он указывает на контекстный узел и всех его потомков, получает текстовые значения, которые не являются пустыми.

об оси XPath

Ответ №3:

Я думаю, что есть лучший способ выполнить эту работу, но у меня есть этот. Я протестировал его в scrapy xpath.Я думаю, это поможет вам.


вывод:


Комментарии:

1. Я хотел бы найти общий способ. Text1 и так далее — это просто случайный пример.

Ответ №4:

Каким-то образом я нашел решение с substring-after


но я хотел бы знать, есть ли лучший способ, чем метод substr .

)»).get())вывод:


Комментарии:

1. Я хотел бы найти общий способ. Text1 и так далее — это просто случайный пример.

Ответ №4:

Каким-то образом я нашел решение с substring-after


но я хотел бы знать, есть ли лучший способ, чем метод substr .

-n
sourceВывод:


Чтобы удалить последнее | перед $ заменой -o '|' на
-v 'substring("|",1,count(following-sibling::*))'
который выдается | только в том случае, если есть больше родственных элементов.

Чтобы добавить поддержку p элементов, например, добавьте | p ко 2-му -m выражению и добавьте <p>Hello from P</p> /html/div в исходный файл.

(Документация --if … --elif … --else … , э-э, менее чем обильная, но, насколько я могу понять, из кода XSLT, выводимого с помощью -C опции, --if предложение завершается -b .)

Я использовал xmlstarlet 1.6.1.

Ответ №2:

Я протестировал некоторые xpath, поэтому лучший, который я нашел, это


результат xpath

Он указывает на контекстный узел и всех его потомков, получает текстовые значения, которые не являются пустыми.

об оси XPath

Ответ №3:

Я думаю, что есть лучший способ выполнить эту работу, но у меня есть этот. Я протестировал его в scrapy xpath.Я думаю, это поможет вам.


вывод:


Комментарии:

1. Я хотел бы найти общий способ. Text1 и так далее — это просто случайный пример.

Ответ №4:

Каким-то образом я нашел решение с substring-after


но я хотел бы знать, есть ли лучший способ, чем метод substr .