#xml #xslt #indexing #key
#xml #xslt #индексирование #Клавиша
Вопрос:
(отредактировано с учетом предложений Мартина Хоннена)
Всем привет,
Я пытался заставить функцию key корректно работать в таблице стилей ниже.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:m="http://mapping.tables" >
<xsl:key name="preferences" match="preferences/preference" use="@code"/>
<xsl:template match="Reservation/Detail" >
<xsl:for-each select="Preferences/Preference">
<xsl:if test ="string-length(./PreferenceCode)>0">
amp;#160;amp;#160;amp;#160;amp;#160;* (<xsl:value-of select="./PreferenceCode"/>)
<xsl:choose>
<xsl:when test="./PreferenceCode!='PETS'">
<xsl:call-template name="prefmap">
<xsl:with-param name="code" select="./PreferenceCode"/>
</xsl:call-template>
<br/><br/>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:template
<xsl:template name="prefmap">
<xsl:param name="code"/>
You got here (called template) with code <xsl:value-of select="$code"/>
<xsl:for-each select="document('')">
<xsl:value-of select="key('preferences',$code)"/>
</xsl:for-each>
</xsl:template>
<m:Maps xmlns="">
<preferences>
<preference code="ANT">
Hypoallergenic Bedding
</preference>
<preference code="NSK">
Non-smoking Room
</preference>
<preference code="SMK">
Smoking Room
</preference>
</preferences>
</m:Maps>
</xsl:stylesheet>
Он принимает входные данные (которые я не контролирую) и выдает это:
* (ANT) You got here (called template) with code ANT
* (EARLY) You got here (called template) with code EARLY
* (NSK) You got here (called template) with code NSK
Когда я ожидал:
* (ANT) You got here (called template) with code ANT
Hypoallergenic Bedding
* (EARLY) You got here (called template) with code EARLY
* (NSK) You got here (called template) with code NSK
Non-smoking Room
Я попытался включить этот фрагмент в основной шаблон для отладки, но это не дало результата:
<xsl:for-each select="key('preferences',./PreferenceCode)">
<p>
Code: <xsl:value-of select="@code"/><br />
Description: <xsl:value-of select="."/>
</p>
</xsl:for-each>
У меня проблема с моим определением ключа или с тем, как я пытаюсь его использовать?
Заранее всем спасибо.
Комментарии:
1. Не могли бы вы, пожалуйста, предоставить (минимально возможный) XML-документ, к которому можно применить это преобразование?
2. Ваша проблема не воспроизводима — я запустил ваше преобразование на 7 разных процессорах XSLT, которые я использую ежедневно. Все они выдали один и тот же правильный результат.
Ответ №1:
Вы пытаетесь поместить данные в свою таблицу стилей с помощью этих preferences/pref
элементов? Разве они не должны находиться в отдельном пространстве имен? И ключи создаются для каждого документа, и key
функция с XSLT 1.0 ищет узлы в документе, к которому принадлежит контекстный узел. Если вы хотите просмотреть узлы в самой таблице стилей, то сначала вам нужно изменить контекстный узел, например, <xsl:for-each select="document('')"><xsl:value-of select="key('preferences', $code)"/></xsl:for-each>
. Затем удалите начало /
из match
значения атрибута и убедитесь, что вы поместили элементы в элемент контейнера в отдельном пространстве имен, например
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:m="http://mapping.tables"
xmlns:data="http://example.com/data">
<xsl:key name="preferences" match="preferences/pref" use="@code"/>
<data:data xmlns="">
<preferences>
<pref code="ANT">
Hypoallergenic Bedding
</pref>
<pref code="NSK">
Non-smoking Room
</pref>
<pref code="SMK">
Smoking Room
</pref>
</preferences>
</data:data>
Комментарии:
1. Спасибо за быстрый ответ. Я применил ваши предложения к работе, но без радости. Теперь я получаю java.lang. Исключение NullPointException всякий раз, когда оно попадает в эту конкретную часть логики. К сожалению, у меня нет доступа ни к одному из серверных интерфейсов, кроме возможности загружать таблицу стилей, поэтому я не могу получить трассировку стека или какую-либо более подробную информацию об ошибках, пока администратор компьютера не свяжется со мной. Однако я буду продолжать работать.
2. Мартин, я не хочу показаться дотошным, но будет ли <xsl:for-each>, который ссылается на фрагмент документа («), который вы предлагаете, помещен в шаблон ‘prefmap’?
3. Саймон,
for-each
фрагмент должен заменить<xsl:value-of select="key('preferences',$code)"/>
.4. И убедитесь, что у вас есть
xmlns=""
наm:Maps
элементе, содержащем этиpreferences
элементы, иначе ваш ключ не будет работать.5. Спасибо. Я внес изменения выше, но я все еще получаю java.lang. Исключение NullPointerException при попытке выполнить поиск.
Ответ №2:
У меня проблема с моим определением ключа или с тем, как я пытаюсь его использовать?
Ни с одним из них проблем нет:
Я не могу воспроизвести сообщенный результат. Это означает, что если действительно есть какая-либо проблема, то она в коде, который нам не показан.
Предоставленное преобразование:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:m="http://mapping.tables" >
<xsl:key name="preferences" match="preferences/preference" use="@code"/>
<xsl:template match="Reservation/Detail" >
<xsl:for-each select="Preferences/Preference">
<xsl:if test ="string-length(./PreferenceCode)>0"> amp;#160;amp;#160;amp;#160;amp;#160;* (
<xsl:value-of select="./PreferenceCode"/>)
<xsl:choose>
<xsl:when test="./PreferenceCode!='PETS'">
<xsl:call-template name="prefmap">
<xsl:with-param name="code" select="./PreferenceCode"/>
</xsl:call-template>
<br/>
<br/>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="prefmap">
<xsl:param name="code"/> You got here (called template) with code
<xsl:value-of select="$code"/>
<xsl:for-each select="document('')">
<xsl:value-of select="key('preferences',$code)"/>
</xsl:for-each>
</xsl:template>
<m:Maps xmlns="">
<preferences>
<preference code="ANT">
Hypoallergenic Bedding
</preference>
<preference code="NSK">
Non-smoking Room
</preference>
<preference code="SMK">
Smoking Room
</preference>
</preferences>
</m:Maps>
</xsl:stylesheet>
при применении к следующему XML-документу (в вопросе не был предоставлен XML-документ!):
<Reservation>
<Detail>
<Preferences>
<Preference>
<PreferenceCode>ANT</PreferenceCode>
</Preference>
<Preference>
<PreferenceCode>NSK</PreferenceCode>
</Preference>
<Preference>
<PreferenceCode>SMK</PreferenceCode>
</Preference>
<Preference>
<PreferenceCode>PETS</PreferenceCode>
</Preference>
</Preferences>
</Detail>
</Reservation>
выдает именно ожидаемый результат:
<?xml version="1.0" encoding="utf-8"?>
* (
ANT)
You got here (called template) with code
ANT
Hypoallergenic Bedding
<br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/><br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/> * (
NSK)
You got here (called template) with code
NSK
Non-smoking Room
<br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/><br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/> * (
SMK)
You got here (called template) with code
SMK
Smoking Room
<br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/><br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/> * (
PETS)
Обратите внимание:
Все следующие 7 процессоров XSLT выдают точно такой же результат (приведенный выше): MSXML3/ 4, XslCompiledTransform, XslTransform, Saxon 6.5.4, Saxon 9.1.05, AltovaXML (XMLSpy).
Комментарии:
1. Спасибо! Я укажу на это разработчику приложения, чтобы им было над чем работать. Выдающиеся усилия Дмитрия и с благодарностью!
2. @Simon: Рад, что мой вопрос был полезен. Здесь, в SO, официальной формой выражения благодарности является принятие правильного ответа. Это делается нажатием на зеленую галочку рядом с ответом. 🙂
3. Кстати, образец XML, который вы прогнали через преобразование, по сути, является именно тем, чем он должен быть как часть в «реальном» документе. Кроме того, если это вообще помогает, мы привыкли обрабатывать настройки с помощью блока <xsl:choose>, который работал довольно хорошо. Основная причина переключения — это просто огромное количество настроек, которые нам теперь нужно включить, которое увеличилось с 5 до 30. Сопоставление (key()) казалось наиболее приемлемым в долгосрочной перспективе, но мы открыты для любых других предложений.
4. @Simon: Как я доказал, это невозможно воспроизвести на основе предоставленных в данный момент данных.
5. Могу ли я принять оба ответа, поскольку оба были очень полезны? Я пытался проголосовать за оба, но моя репутация слишком низкая. 🙁