XML и XSLT - значение параметра не в формате XML

У меня есть файл XML с несколькими записями и разными значениями (например, список элементов со значениями, такими как их имя, количество, вес и т. д.). Я использую XSLT, чтобы показать их в виде таблицы на веб-странице. На каждой отдельной странице отображается другая запись — xslt берет значение параметра с веб-страницы, а затем отображает только соответствующие фрагменты информации. Например, есть веб-страница, посвященная предмету XYZ - показано только название, номер и вес этого конкретного предмета.

Мой вопрос заключается в том, есть ли способ показать какое-то сообщение (например, «Для этого элемента нет данных»), когда такого элемента в XML нет. Не то, чтобы параметр был пустым или нулевым - он все равно берется с веб-страницы. Просто в файле XML такой записи нет.

Любая помощь, пожалуйста?

Вы можете найти код для файлов XML и XLS ниже. Я изменил имена и значения параметров/переменных, но все остальное осталось таким же, как и в исходном файле.

XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ItemsTable>
<ItemRow>
    <item>001</item>
    <name>aaaa</name>
    <price>2402</price>
    <price2>2200</price2>
</ItemRow>
<ItemRow>
    <item>002</item>
    <name>bbbb</name>
    <price>2402</price>
    <price2>2700</price2>
</ItemRow>
<ItemRow>
    <item>003</item>
    <name>cccc</name>
    <price>2402</price>
    <price2>2003</price2>
</ItemRow>
<ItemRow>
    <item>004</item>
    <name>dddd</name>
    <price>2402</price>
    <price2>2024</price2>
</ItemRow>

XSL:

  <?xml version="1.0" encoding="ISO-8859-1" ?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="thisitem">XXXX</xsl:param> 
<xsl:template match="/">
<xsl:apply-templates /> 
</xsl:template>
<xsl:decimal-format name="european" decimal-separator="," grouping-separator="." /> 
<xsl:template match="/ItemsTable/ItemRow" /> 
<xsl:template match="/ItemsTable/ItemRow [ item = $thisitem ]">
<style>table.YYY { border-collapse: collapse; } table.YYY td, table.YYY th { border: 1px solid black; padding: 1em; vertical-align: middle; text-align: center; } table.YYY th { background-color: #eee; } table.YYY .header { font-size: 2em; font-weight: bold; padding-bottom: 1em; padding-top: 1em; } table.YYY .itemname { color: red; font-weight: bold; white-space: nowrap; } table.YYY .yellow { background-color: yellow; } table.YYY .red { background-color: red; } table.YYY .green { background-color: #40FF00; }</style> 
<html>
<body>
<table class="YYY">
<xsl:if test="string-length(name) > 0 and string-length(price) > 0 and string-length(price2) > 0" /> 
<xsl:choose>
<xsl:when test="string-length(name) > 0 and string-length(price) > 0 and string-length(price2) > 0">
<tr>
<th>Name</th> 
<th>Price 1</th> 
<th>Price 2</th> 
</tr>
<tr>
<xsl:choose>
<xsl:when test="price > price2">
<td class="red">
<xsl:value-of select="name" /> 
</td>
<td class="red">
<xsl:value-of select="format-number(price, '###.###.###', 'european')" /> 
</td>
<td class="red">
<xsl:value-of select="format-number(price2, '###.###.###', 'european')" /> 
</td>
</xsl:when>
<xsl:otherwise>
<td class="green">
  <xsl:value-of select="name" /> 
</td>
<td class="green">
  <xsl:value-of select="format-number(price, '###.###.###', 'european')" /> 
</td>
<td class="green">
  <xsl:value-of select="format-number(price2, '###.###.###', 'european')" /> 
</td>
</xsl:otherwise>
</xsl:choose>
</tr>
</xsl:when>
<xsl:otherwise>
<div>
  <p>No data for this item</p> 
</div>
</xsl:otherwise>
</xsl:choose>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

person Marta    schedule 12.09.2012    source источник
comment
Можете ли вы показать XSLT, который у вас есть на данный момент, и пример типа XML, который у вас есть в качестве входных данных?   -  person Ian Roberts    schedule 12.09.2012
comment
Конечно. Я изменил имена и значения параметров/переменных, но и XML, и XSL построены точно так же, как показано ниже.   -  person Marta    schedule 12.09.2012
comment
Я знаю - извините, случайно нажал энтер. Теперь он находится в описании вопроса, так как он слишком длинный для комментария.   -  person Marta    schedule 12.09.2012


Ответы (1)


Помимо того, что

<xsl:template match="/ItemsTable/ItemRow [ item = $thisitem ]">

недопустимо в XSLT 1.0 (вы не можете использовать переменные в выражениях сопоставления для каждой спецификации, но некоторые процессоры все равно их принимают), ваша проблема здесь в том, что шаблоны срабатывают только тогда, когда существуют элементы, которым они соответствуют. Если нет ItemRow, чей item дочерний элемент является тем, о котором вы просите, шаблон вообще не сработает.

Вместо этого вам нужно переместить логику «нет данных для этого элемента» в шаблон для родительского ItemsTable

<xsl:template match="/ItemsTable">
  <xsl:variable name="matchingRows" select="ItemRow[item = $thisitem][string-length(name)][string-length(price)][string-length(price2)]"/>
  <xsl:choose>
    <xsl:when test="$matchingRows">
      <xsl:apply-templates select="$matchingRows"/>
    </xsl:when>
    <xsl:otherwise>
      <div>
        <p>No data for this item</p> 
      </div>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="ItemRow">
  <!-- logic for each matching row here, don't need to check the
       preconditions as the template is only called for rows that match -->
</xsl:template>
person Ian Roberts    schedule 12.09.2012
comment
Спасибо! Работает как шарм :) - person Marta; 13.09.2012