#xml #xslt
#xml #xslt
Вопрос:
Я хотел бы отсортировать свой XML-файл по двум признакам: идентификатору и влиянию. Я хотел бы упорядочить элементы по идентификатору, ЗА исключением элементов, у которых есть XX product, который должен появиться последним.
Мой XML-файл
<evolutionlist>
<date>
<object>
<identifier>id5</identifier>
<impact>
<product>AA</produit>
</impact>
</objet>
<object>
<identifier>id2</identifier>
<impact>
<product>XX</produit>
</impact>
</objet>
<object>
<identifier>id4</identifier>
<impact>
<product>BB</produit>
</impact>
</objet>
<object>
<identifier>id3</identifier>
<impact>
<product>XX</produit>
</impact>
</objet>
<object>
<identifier>id1</identifier>
<impact>
<product>CC</produit>
</impact>
</objet>
</date>
</evolutionlist>
Ожидаемый результат будет:
<evolutionlist>
<date>
<object>
<identifier>id1</identifier>
<impact>
<product>CC</produit>
</impact>
</objet>
<object>
<identifier>id4</identifier>
<impact>
<product>BB</produit>
</impact>
</objet>
<object>
<identifier>id5</identifier>
<impact>
<product>AA</produit>
</impact>
</objet>
<object>
<identifier>id2</identifier>
<impact>
<product>XX</produit>
</impact>
</objet>
<object>
<identifier>id3</identifier>
<impact>
<product>XX</produit>
</impact>
</objet>
</date>
</evolutionlist>
мой код xslt (хотя и не работает)
<xsl:for-each select="//date">
<tr>
<td>
<xsl:value-of select="./@id"/>
</td>
</tr>
<xsl:for-each select="./object">
<xsl:choose>
<xsl:when test="impact/produit = 'XX'">
<xsl:sort select="impact/produit" order="descending"/>
</xsl:when>
<xsl:otherwise>
<xsl:sort select="identifiant"/>
</xsl:otherwise>
</xsl:choose>
...
</xsl:for-each>
Ответ №1:
Вы можете поместить a <xsl:sort>
в начало <xsl:for-each>
или <xsl:apply-templates/>
, а не в <choose>
блок.
Вы используете сортировку для упорядочивания XX
, поэтому я предполагаю, что в вашем сценарии это нормально (например: у вас нет имени продукта ZZ
, которое было бы помещено после XX
). Если это не так, вам следует использовать не sort
для этого правила, а шаблон, который соответствует XX
содержимому и помещает его в конец.
Эта таблица стилей выдает ожидаемые результаты, используя sort
правила, которые у вас есть в исходной таблице стилей (упорядочение по идентификаторам и строкам продуктов). Я переместил правила выбора в предикат XPath и использовал шаблоны вместо вложенных for-each
узлов.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="date">
<xsl:apply-templates select="object">
<xsl:sort select="impact/product[. = 'XX']" order="ascending"/>
<xsl:sort select="identifier"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Вы можете попробовать это в этой скрипке XSLT
ОБНОВЛЕНИЕ В случае, если вы на самом деле не хотите заказывать XX
продукты, но всегда размещаете их в конце, вы можете отфильтровать эти элементы и применить их шаблоны после обработки других элементов. Это делает другая таблица стилей:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="date">
<xsl:apply-templates select="object[not(impact[product = 'XX'])]">
<xsl:sort select="identifier"/>
</xsl:apply-templates>
<xsl:apply-templates select="object[impact[product = 'XX']]"/>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Вот еще одна скрипка XSLT с этим примером.
Комментарии:
1. спасибо за помощь, это более понятно, к сожалению, у меня могут быть продукты ZZ, которые должны быть отсортированы по их идентификатору, в конце должны отображаться только продукты XX, извините, я был недостаточно точен
2. вот почему я использовал условие «когда»
3. Вам не нужно
when
. Вы можете выбирать с помощью шаблонов и предикатов, что также более эффективно. Я добавил решение, помещающееXX
элементы в конец.4. большое спасибо! Это именно то, что мне нужно, решение очень четкое!
5. и спасибо за подсказку по скрипке XSLT! Я этого не знал !