#xslt
#xslt
Вопрос:
Как я могу включить оператор if в мое условие цикла в XSLT?
У меня есть 2 или 3 разных сценария, которые определяют данные, которые я хочу просмотреть. Например, может быть или не быть идентификатор продукта. Если есть, я хочу перебирать только записи, содержащие этот идентификатор продукта, в противном случае мне нужны все записи. Я пытался сделать что-то вроде этого:
<xsl:variable name="knowledgebaseLoop">
<xsl:choose>
<xsl:when test="string-length($productId) amp;> 0">
<xsl:copy-of select="$currentPage/child::* [@parentID = $parentId]"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$currentPage/child::* [@parentID = $parentId]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:for-each select="knowledgebaseLoop">
<xsl:if test="position() amp;> $recordsPerPage * number($pageNumber - 1) and position() amp;<= number($recordsPerPage * number($pageNumber - 1) $recordsPerPage )">
<div id="main_body_listing">
<div class="listing_title2"><a href="{umbraco.library:NiceUrl(current()/@id)}"><xsl:value-of select="current()/@nodeName"/></a></div>
<xsl:value-of select="current()/summary"/>
</div>
</xsl:if>
</xsl:for-each>
Но он не может проанализировать XSLT. Я знаю, что два условия одинаковы, я собирался переписать одно, как только оно заработает. Заранее спасибо за любую помощь!
Обновить:
Вот несколько примеров XML:
<Knowledgebase id="1073" parentID="-1" level="1" writerID="0" creatorID="0" nodeType="1062" template="1083" sortOrder="5" createDate="2011-04-20T13:43:41" updateDate="2011-05-11T14:34:23" nodeName="Knowledgebase" urlName="knowledgebase" writerName="Chris" creatorName="Chris" path="-1,1073" isDoc=""><pageTitle>Knowledgebase</pageTitle><metaDescription>knowledgebase</metaDescription><metaKeywords>knowledgebase</metaKeywords><umbracoUrlName /><Article id="1074" parentID="1073" level="2" writerID="0" creatorID="0" nodeType="1063" template="1084" sortOrder="1" createDate="2011-04-20T13:44:13" updateDate="2011-05-16T09:39:12" nodeName="What is the answer to this question?" urlName="what-is-the-answer-to-this-question" writerName="Chris" creatorName="Chris" path="-1,1073,1074" isDoc=""><title>Change 2 Test 2</title><summary>Change 2 Test 2</summary><description>
amp;<pamp;>amp;<strongamp;>Change 2 Test 2amp;<br /amp;>
amp;</strongamp;>amp;</pamp;>
</description><relatedProducts>1071,1076</relatedProducts><pageTitle>asd</pageTitle><metaDescription>asd</metaDescription><metaKeywords>asd</metaKeywords><umbracoUrlName /></Article><Article id="1082" parentID="1073" level="2" writerID="0" creatorID="3" nodeType="1063" template="1084" sortOrder="2" createDate="2011-05-04T09:59:31" updateDate="2011-05-11T14:34:23" nodeName="Question 2" urlName="question-2" writerName="Chris" creatorName="Content Writer" path="-1,1073,1082" isDoc=""><title>test</title><summary>test 22</summary><description>
amp;<pamp;>tstamp;</pamp;>
</description><relatedProducts>1075</relatedProducts><pageTitle /><metaDescription></metaDescription><metaKeywords></metaKeywords><umbracoUrlName /></Article><Article id="1146" parentID="1073" level="2" writerID="4" creatorID="3" nodeType="1063" template="1084" sortOrder="3" createDate="2011-05-13T15:36:14" updateDate="2011-05-13T15:37:21" nodeName="Question 3" urlName="question-3" writerName="Content Approver" creatorName="Content Writer" path="-1,1073,1146" isDoc=""><title>Test</title><summary></summary><description>
amp;<pamp;>Testamp;</pamp;>
</description><relatedProducts /><pageTitle>Test</pageTitle><metaDescription>test</metaDescription><metaKeywords>test</metaKeywords><umbracoUrlName /></Article></Knowledgebase>
Мне всегда нужны статьи, в которых родительский идентификатор равен 1073. Если и только если идентификатор продукта существует, я хочу, чтобы статьи, в которых идентификатор продукта находится в списке relatedProducts. Еще раз спасибо!
Комментарии:
1. Хороший вопрос, 1. Смотрите мой ответ для полного, короткого и простого однострочного решения для выражения XPath. 🙂
2. >»Но он не может проанализировать XSLT». — есть ли сообщение об ошибке? Если это так, то всем было бы проще, если бы вы рассказали нам о сообщении.
3. Будет ли это? Тогда ладно. В сообщении очень креативно говорится «Не удается проанализировать базу знаний.xslt».
Ответ №1:
Например, может быть или не быть идентификатор продукта. Если есть, я хочу перебирать только записи, содержащие этот идентификатор продукта, в противном случае мне нужны все записи.
Мне всегда нужны статьи, в которых родительский идентификатор равен 1073. Тогда и только тогда, когда идентификатор продукта существует, мне нужны статьи, в
relatedProducts
списке которых есть идентификатор продукта.
Использовать:
<xsl:variable name="vDesiredArticles" select=
"/*/Article[@parentID='1073'
or
contains(concat(',',relatedProducts,','),
concat(',', $pProductId, ',')
)
]"/>
Вот полный и краткий пример:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pProductId" select="1077"/>
<xsl:template match="/">
<xsl:variable name="vDesiredArticles" select=
"/*/Article[@parentID='1073'
or
contains(concat(',',relatedProducts,','),
concat(',', $pProductId, ',')
)
]"/>
<xsl:copy-of select="$vDesiredArticles"/>
</xsl:template>
</xsl:stylesheet>
когда это преобразование применяется к следующему XML-документу (на основе предоставленного в обновлении, но сделанного более интересным):
<Knowledgebase id="1073" parentID="-1" level="1" writerID="0"
creatorID="0" nodeType="1062" template="1083" sortOrder="5"
createDate="2011-04-20T13:43:41" updateDate="2011-05-11T14:34:23"
nodeName="Knowledgebase" urlName="knowledgebase" writerName="Chris"
creatorName="Chris" path="-1,1073" isDoc="">
<pageTitle>Knowledgebase</pageTitle>
<metaDescription>knowledgebase</metaDescription>
<metaKeywords>knowledgebase</metaKeywords>
<umbracoUrlName />
<Article id="1074" parentID="1073" level="2"
writerID="0" creatorID="0" nodeType="1063" template="1084"
sortOrder="1" createDate="2011-04-20T13:44:13"
updateDate="2011-05-16T09:39:12"
nodeName="What is the answer to this question?"
urlName="what-is-the-answer-to-this-question" writerName="Chris"
creatorName="Chris" path="-1,1073,1074" isDoc="">
<title>Change 2 Test 2</title>
<summary>Change 2 Test 2</summary>
<description> amp;<pamp;>amp;<strongamp;>Change 2 Test 2amp;<br /amp;> amp;</strongamp;>amp;</pamp;> </description>
<relatedProducts>1071,1076</relatedProducts>
<pageTitle>asd</pageTitle>
<metaDescription>asd</metaDescription>
<metaKeywords>asd</metaKeywords>
<umbracoUrlName />
</Article>
<Article id="1082" parentID="1073" level="2" writerID="0" creatorID="3" nodeType="1063" template="1084" sortOrder="2" createDate="2011-05-04T09:59:31" updateDate="2011-05-11T14:34:23" nodeName="Question 2" urlName="question-2" writerName="Chris" creatorName="Content Writer" path="-1,1073,1082" isDoc="">
<title>test</title>
<summary>test 22</summary>
<description> amp;<pamp;>tstamp;</pamp;> </description>
<relatedProducts>1075</relatedProducts>
<pageTitle />
<metaDescription></metaDescription>
<metaKeywords></metaKeywords>
<umbracoUrlName />
</Article>
<Article id="1088" parentID="1077" level="2" writerID="0" creatorID="3" nodeType="1063" template="1084" sortOrder="2" createDate="2011-05-04T09:59:31" updateDate="2011-05-11T14:34:23" nodeName="Question 2" urlName="question-2" writerName="Chris" creatorName="Content Writer" path="-1,1073,1082" isDoc="">
<title>test</title>
<summary>test 22</summary>
<description> amp;<pamp;>tstamp;</pamp;> </description>
<relatedProducts>1075,1039,1077</relatedProducts>
<pageTitle />
<metaDescription></metaDescription>
<metaKeywords></metaKeywords>
<umbracoUrlName />
</Article>
<Article id="1089" parentID="1077" level="2" writerID="0" creatorID="3" nodeType="1063" template="1084" sortOrder="2" createDate="2011-05-04T09:59:31" updateDate="2011-05-11T14:34:23" nodeName="Question 2" urlName="question-2" writerName="Chris" creatorName="Content Writer" path="-1,1073,1082" isDoc="">
<title>test</title>
<summary>test 22</summary>
<description> amp;<pamp;>tstamp;</pamp;> </description>
<relatedProducts>1075,1039,1078</relatedProducts>
<pageTitle />
<metaDescription></metaDescription>
<metaKeywords></metaKeywords>
<umbracoUrlName />
</Article>
<Article id="1146" parentID="1073" level="2" writerID="4" creatorID="3" nodeType="1063" template="1084" sortOrder="3" createDate="2011-05-13T15:36:14" updateDate="2011-05-13T15:37:21" nodeName="Question 3" urlName="question-3" writerName="Content Approver" creatorName="Content Writer" path="-1,1073,1146" isDoc="">
<title>Test</title>
<summary></summary>
<description> amp;<pamp;>Testamp;</pamp;> </description>
<relatedProducts />
<pageTitle>Test</pageTitle>
<metaDescription>test</metaDescription>
<metaKeywords>test</metaKeywords>
<umbracoUrlName />
</Article>
</Knowledgebase>
получен желаемый, правильный результат (только статьи с parentID="1073"
или чьи relatedProducts
содержат $pProductId
(1077)):
<Article id="1074" parentID="1073" level="2" writerID="0" creatorID="0" nodeType="1063" template="1084" sortOrder="1" createDate="2011-04-20T13:44:13" updateDate="2011-05-16T09:39:12" nodeName="What is the answer to this question?" urlName="what-is-the-answer-to-this-question" writerName="Chris" creatorName="Chris" path="-1,1073,1074" isDoc="">
<title>Change 2 Test 2</title>
<summary>Change 2 Test 2</summary>
<description> amp;<pamp;>amp;<strongamp;>Change 2 Test 2amp;<br /amp;> amp;</strongamp;>amp;</pamp;> </description>
<relatedProducts>1071,1076</relatedProducts>
<pageTitle>asd</pageTitle>
<metaDescription>asd</metaDescription>
<metaKeywords>asd</metaKeywords>
<umbracoUrlName/>
</Article>
<Article id="1082" parentID="1073" level="2" writerID="0" creatorID="3" nodeType="1063" template="1084" sortOrder="2" createDate="2011-05-04T09:59:31" updateDate="2011-05-11T14:34:23" nodeName="Question 2" urlName="question-2" writerName="Chris" creatorName="Content Writer" path="-1,1073,1082" isDoc="">
<title>test</title>
<summary>test 22</summary>
<description> amp;<pamp;>tstamp;</pamp;> </description>
<relatedProducts>1075</relatedProducts>
<pageTitle/>
<metaDescription/>
<metaKeywords/>
<umbracoUrlName/>
</Article>
<Article id="1088" parentID="1077" level="2" writerID="0" creatorID="3" nodeType="1063" template="1084" sortOrder="2" createDate="2011-05-04T09:59:31" updateDate="2011-05-11T14:34:23" nodeName="Question 2" urlName="question-2" writerName="Chris" creatorName="Content Writer" path="-1,1073,1082" isDoc="">
<title>test</title>
<summary>test 22</summary>
<description> amp;<pamp;>tstamp;</pamp;> </description>
<relatedProducts>1075,1039,1077</relatedProducts>
<pageTitle/>
<metaDescription/>
<metaKeywords/>
<umbracoUrlName/>
</Article>
<Article id="1146" parentID="1073" level="2" writerID="4" creatorID="3" nodeType="1063" template="1084" sortOrder="3" createDate="2011-05-13T15:36:14" updateDate="2011-05-13T15:37:21" nodeName="Question 3" urlName="question-3" writerName="Content Approver" creatorName="Content Writer" path="-1,1073,1146" isDoc="">
<title>Test</title>
<summary/>
<description> amp;<pamp;>Testamp;</pamp;> </description>
<relatedProducts/>
<pageTitle>Test</pageTitle>
<metaDescription>test</metaDescription>
<metaKeywords>test</metaKeywords>
<umbracoUrlName/>
</Article>
Комментарии:
1. Дмитрий — это мой предпочтительный метод решения этой проблемы — я действительно не хочу иметь несколько шаблонов, потому что может быть несколько случаев, и шаблон фактически один и тот же, просто результаты отличаются. Однако это не ParentID, мне нужно проверить, что это ProductID, и связанные продукты могут быть списком. Я попробовал следующее, но, похоже, это не сработало: <xsl:for-each select=»$ currentPage / дочерний элемент::* [@ParentID = $ParentID] [содержит (@relatedProducts, $ ProductID) или нет ($ ProductID)]»>
2. @Dexter: Тогда я в замешательстве — в предоставленном вами коде, который вы используете
$parentID
. Это ошибка? Вероятно, вам нужно отредактировать вопрос и уточнить / исправить это.3. @Dimitre: Нет, все правильно, $ParentID — это одна из переменных, которые я использую. $ParentID всегда будет существовать. Мне нужно также проверить наличие $ProductID, если он существует. Имеет ли это смысл? Прошу прощения, если это было неясно.
4. @Dexter: Тогда я не понимаю вопроса. Не могли бы вы, пожалуйста, предоставить образец XML-документа (как можно меньшего размера) и описать, каким должен быть результат — лучше всего также предоставить точный ожидаемый результат?
5. @Dimitre только что обновил пример, дайте мне знать, если это поможет. Еще раз спасибо за всю вашу помощь!!
Ответ №2:
Я бы использовал xsl:choose
(чтобы получить часть else с помощью xsl:otherwise
) плюс шаблон:
<xsl:choose>
<xsl:when test='@productId'>
<xsl:apply-templates select='filter by product id' />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select='all of them' />
</xsl:otherwise>
А затем определите шаблон для обработки списка узлов.
Ответ №3:
Вы можете выполнить проверку в конструкции цикла foreach, например:
<xsl:for-each select="item[@productId != '']">
Условие в [] после элемента в select указывает, что вам нужны только элементы с этим атрибутом, соответствующим условию. Итак, что-то вроде этого будет соответствовать:
< идентификатор продукта элемента=»BR9ES»>
Но это не привело бы к: < элемент>
Комментарии:
1. Что, если идентификатор продукта не существует, и я вообще не хочу включать его в сравнение? Как мне проверить оба случая?
2. Вы могли бы использовать второй цикл, подобный этому: <xsl:для каждого select=»item[@ProductID = «]»>
Ответ №4:
Это то, что я использую, чтобы проверить, существует ли элемент в моем XML-документе:
<xsl:if test="@productID[.!='']"> //if it is not empty
<xsl:value-of select="@productID"/>
</xsl:if>
Комментарии:
1. Что, если идентификатор продукта не существует, и я вообще не хочу включать его в сравнение? Как мне проверить оба случая?