XPath для выбора всего текста в заданном node и текста его chldren
В основном мне нужно очистить текст, содержащий вложенные теги.
Что-то вроде этого:
<div id='theNode'>
This is an <span style="color:red">example</span> <b>bolded</b> text
</div>
И я хочу выражение, которое произведет это:
This is an example bolded text
Я боролся с этим в течение часа или более без результата.
Любая помощь приветствуется
Ответы
Ответ 1
string-value элемента node является конкатенацией строковых значений всех текстовых node потомков элемента node в порядке документа.
Вы хотите вызвать функцию XPath string()
в элементе div.
string(//div[@id='theNode'])
Вы также можете использовать функцию normalize-space, чтобы уменьшить нежелательные пробелы, которые могут появиться из-за новых строк и отступов в исходном документе. Это приведет к удалению начального и конечного пробелов и замену последовательностей пробельных символов одним пробелом. Когда вы передаете набор узлов в normalize-space(), узел node сначала будет преобразован в него строковым значением. Если аргументы не передаются в normalize-space, он будет использовать контекст node.
normalize-space(//div[@id='theNode'])
// if theNode was the context node, you could use this instead
normalize-space()
Возможно, вы захотите использовать более эффективный способ выбора контекста node, чем пример XPath, который я использовал. например, в некоторых браузерах на этой странице может быть запущен следующий пример Javascript.
var el = document.getElementById('question');
var result = document.evaluate('normalize-space()', el, null ).stringValue;
Простым текстовым текстом node между элементами span
и b
может быть проблема.
Ответ 2
Использование
string(//div[@id='theNode'])
Когда это выражение оценивается, результатом является строковое значение первого (и, надеюсь, только) div
элемента в документе.
Поскольку строковое значение элемента определяется в Спецификация XPath как конкатенация в порядке документа всех его текстовых потомков node, это точно искомая строка.
Поскольку это может включать в себя несколько текстовых узлов с полным пробелом, вы можете устранить смежное ведущее и конечное белое пространство и заменить любое такое промежуточное белое пространство на один пробельный символ:
Использование
normalize-space(string(//div[@id='theNode']))
Проверка на основе XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
"<xsl:copy-of select="string(//div[@id='theNode'])"/>"
===========
"<xsl:copy-of select="normalize-space(string(//div[@id='theNode']))"/>"
</xsl:template>
</xsl:stylesheet>
, когда это преобразование применяется к предоставленному XML-документу:
<div id='theNode'> This is an
<span style="color:red">example</span>
<b>bolded</b> text
</div>
вычисляются два выражения XPath и результаты этих оценок копируются в выходной файл:
" This is an
example
bolded text
"
===========
"This is an example bolded text"
Ответ 3
Как насчет этого:
/div/text() [1] |/div/span/text() |/div/b/text() |/div/text() [2]
Hmmss Я не уверен в последней части. Возможно, вам придется играть с этим.
Ответ 4
Если вы используете scrapy в python, вы можете использовать descendant-or-self::*/text()
. Полный пример:
txt = """<div id='theNode'>
This is an <span style="color:red">example</span> <b>bolded</b> text
</div>"""
selector = scrapy.Selector(text=txt, type="html") # Create HTML doc from HTML text
all_txt = selector.xpath('//div/descendant-or-self::*/text()').getall()
final_txt = ''.join( _ for _ in all_txt).strip()
print(final_txt) # 'This is an example bolded text'