Требуется помощь с XSLT для каждого, использующего XPATH

#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>