Использование значения элемента XML в предикате XSLT - PullRequest
0 голосов
/ 25 февраля 2010

Я не совсем уверен, возможно ли это с XSLT, и мой лектор понятия не имел, о чем я говорю, поэтому, если кто-то может помочь, спасибо !!!

У меня есть XML-файл со списком авторов, каждый с уникальным идентификатором, и списком книг, каждый из которых имеет дочерний элемент со значением IDREF в качестве значения. Файл выложен так:

<library>
  <authors>
    <author id="a001">
       <name>Joyce</name>
    </author>
  </authors>
  <books>
    <book id="b001">
      <name>Illiad</name>
      <authorID>a001</authorID>
    </book>
  </books>
</library>

Я пытаюсь выписать список всех книг и, используя значение authorID, получить информацию об авторе.

XSLT:

<?xml version="1.0" encoding="UTF-8"?>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>XSLT Test</title>
</head>

<body>
    <xsl:for-each select="//book">
     <div style="display:block; background-color:#999; padding:2px; margin:2px;">
         <h2><xsl:value-of select="name"/></h2>
            <p><xsl:value-of select="synopsis"/></p>
            <ul>
             <li>Author: <xsl:value-of select="//author[@id='X']/name"/></li>
            </ul>
        </div>
    </xsl:for-each>
</body>
</html>

Заменив X значением, например, a001, я могу вернуть Джойса, но как вместо этого использовать здесь значение authorID, чтобы система хорошо масштабировалась?

Ответы [ 3 ]

6 голосов
/ 25 февраля 2010

Избегайте оператора //. У него, как правило, не самые лучшие характеристики, особенно когда вы вкладываете его так, как делаете (for-each //, value-of //)

Используйте канонические выражения XPath, как это. Они работают намного лучше:

<xsl:for-each select="/library/books/book">
  <div style="display:block; background-color:#999; padding:2px; margin:2px;">
    <h2><xsl:value-of select="name"/></h2>
    <p><xsl:value-of select="synopsis"/></p>
    <ul>
      <li>
        <xsl:text>Author: </xsl:text>
        <!-- use the current() function to access the current node (book) -->
        <xsl:value-of select="
          /library/authors/author[@id=current()/authorID]/name
        "/>
      </li>
    </ul>
  </div>
</xsl:for-each>

Еще лучше объявить ключ XSL:

<xsl:key name="kAuthorById" match="author" use="@id" />

и доступ к нему с помощью функции key():

<xsl:value-of select="key('kAuthorById', authorID)/name" />

Этот метод обладает лучшими показателями, особенно когда входные документы становятся больше.

Вам также следует избегать <xsl:for-each>. Попробуйте написать шаблоны и использовать сопоставление с шаблоном:

<xsl:template match="library">
  <body>
    <xsl:apply-templates select="books" />
  </body>
</xsl:template>

<xsl:template match="books">
  <h1>List of Books</h1>
  <xsl:apply-templates select="book" />
</xsl:template>

<xsl:template match="book">
  <div style="display:block; background-color:#999; padding:2px; margin:2px;">
    <h2><xsl:value-of select="name"/></h2>
    <p><xsl:value-of select="synopsis"/></p>
    <ul>
      <li>Author: <xsl:value-of select="key('kAuthorById', authorID)/name"/></li>
    </ul>
    </div>
</xsl:template>
0 голосов
/ 25 февраля 2010
<xsl:template match="book">
    <xsl:variable name="authorID" select="@authorID"/>

    <div>
        <h2><xsl:value-of select="name"/></h2>
        <p><xsl:value-of select="synopsis"/></p> 
        <xsl:for-each select="/library/authors/author[@id=$authorID]">
            <ul>
                <li>Author: <xsl:value-of select="name"/></li>
            </ul>
        </xsl:for-each>
    </div>
</xsl:template>
0 голосов
/ 25 февраля 2010

Вы можете использовать переменную

<xsl:variable name="author" select="authorID/text()" />

и затем используйте его в предикате

<xsl:value-of select="//author[@id=$author]/name"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...