#xml #xslt #xpath
#xml #xslt #xpath
Вопрос:
Я работаю над проектом, который использует XSLT для преобразования HTML-строки для извлечения некоторых конкретных значений. Не могли бы вы, пожалуйста, взглянуть на HTML / XSLT ниже и посмотреть, что я делаю неправильно?
Кстати, в приведенном ниже HTML-файле мне нужно извлечь значение из <a>
, в котором говорится «что-то» (XPATH = //div [@id=’result’]/div[2] / div [1] / a[1]):
<html>
<head></head>
<body>
<div>
<div id="whatever">
<!--other stuff-->
</div>
<div id="whatever2">
<!--other stuff-->
<div>
<div class='listtable'>
<div>
<div id="result">
<div class="ignore">
<!--other stuff-->
</div>
<div>
<div>
<a>something</a>
</div>
</div>
</div>
</div>
<div>
<div id="result">
<div class="ignore">
<!--other stuff-->
</div>
<div>
<div>
<a>something</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
итак, XSLT, который я придумал, выглядит следующим образом, но он не работает…
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My Link Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
</tr>
<xsl:for-each select="//div[@id='result']">
<tr>
<td><xsl:value-of select="/div[2]/div[1]/a[1]"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
PS: Я работал с XPATHS раньше, но у меня нет опыта работы с XSLT, и по какой-то причине Visual Studio вылетает при попытке отладки, поэтому я понятия не имею, что здесь пошло не так.
Спасибо за вашу помощь!
Комментарии:
1. Хороший вопрос, 1. Смотрите мой ответ для подробного объяснения и простого решения. 🙂
Ответ №1:
Относительное Важно понимать разницу между и абсолютными выражениями XPath.
Абсолютное выражение XPath начинается с символа ‘/’.
/div[2]/div[1]/a[1]
ничего не выбирается, если верхний элемент XML-документа не назван div
С другой стороны, выражения XPath внутри <xsl:for-each>
или внутри <xsl:template>
чаще всего предназначены для выбора узлов за пределами текущего узла в. Для этого они должны быть относительными.
Относительное выражение XPath никогда не начинается с ‘/’.
Итак, в вашем случае вам необходимо иметь:
div[2]/div[1]/a[1]
Комментарии:
1. Спасибо за упрощение!!
2. 1 хорошее объяснение. «ничего не выбирает, если верхний элемент XML-документа не имеет имени div» — фактически он ничего не выбирает, если нет второго верхнего
<div>
элемента! Что означает, что входные данные представляют собой не документ, а фрагмент XML.3. @LarsH: Спасибо. Да, упомянутое мной условие является лишь одним из необходимых условий — достаточно, чтобы это (только одно из них) не выполнялось для всего выражения, чтобы не выбирать какой-либо узел 🙂
Ответ №2:
что я делаю не так?
Это всего лишь небольшая ошибка, которую вы совершаете. XPath должен быть:
"div[2]/div[1]/a[1]"
Таким образом, вы правильно выбираете элементы, начиная с текущего контекста xsl:for-each
. Указанным вами способом (с косой чертой в начале XPath) вы пытаетесь выбрать элементы, начинающиеся всегда с корня входного документа.
по какой-то причине Visual Studio выходит из строя при попытке отладки, поэтому я понятия не имею, что здесь пошло не так.
Сбой Visual Studio, вероятно, вызван тем, что в нем есть какой-то недостаток. Возможно, вам нужен какой-то патч. Предоставленный вами XSLT является правильным и никогда не приведет к сбою с процессором XSLT. Вы также должны получить успешный результат со следующим идентичным преобразованием:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My Link Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
</tr>
<xsl:apply-templates select="//div[@id='result']"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="div[@id='result']">
<tr>
<td><xsl:value-of select="div[2]/div[1]/a[1]"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>