2012-05-21 4 views
1

Мне нужно построить строку из чисел, расположенных в разных узлах моего источника xml, но оговорки состоят в том, что порядок узлов datarate будет случайным, а стартовый номер должен начинаться не менее 600 Если нет 600, начните с 800.Номера сортировки XSL из разных узлов

<datarate rate="200" /> 
<datarate rate="600" /> 
<datarate rate="300" /> 
<datarate rate="400" /> 
<datarate rate="800" /> 
<datarate rate="1000" /> 

http://example.com/src/600/800/ 

Я пробовал сортировку по группам, но безрезультатно. У кого-нибудь есть идея?

Спасибо за любую помощь, которую вы можете предоставить!

+0

Можете ли вы привести конкретный пример того, как вы хотите, чтобы строка выглядела? Кроме того, используете ли вы XSLT/XPath 1.0 или 2.0? – Dabbler

ответ

1

С XSLT 2 вы можете сделать это:

<xsl:template match="/"> 
    <xsl:for-each select="//datarate[number(@rate) ge 600]"> 
     <xsl:sort select="@rate" data-type="number"/> 
     <xsl:value-of select="@rate"/> 
     <xsl:if test="not(position() eq last())"> 
     <xsl:text>, </xsl:text> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 
+0

вам все равно нужно сделать что-нибудь, если/then/else вокруг условия «600» или «800», верно? и имея XSLT 2.0, вы можете использовать 'separator'' xsl: value-of' и не выполнять идиому XSLT 1.0 вокруг 'position()! - last()' –

+0

@Pavel Veller: Что делать, если/then/иначе ты имеешь в виду? Результат: 600, 800, 1000. Кроме того, я не совсем понимаю, как поможет 'separator', поскольку каждый' xsl: value-of' работает на одном элементе. – Dabbler

+0

вы правы в отношении 'xsl: value-of' внутри' for-each'. if/then/else связано с требованием @ hybrid9 ', если нет 600, а затем начинается с 800'. Я решил, что если нет 600, 650 или 750, это не сделало бы –

0

Если вы знали, что пороговое число авансом вы могли бы сделать очень просто преобразовать так:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" encoding="UTF-8"/> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="//datarate"> 
      <xsl:sort select="@rate" data-type="number"/> 
     </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="datarate[@rate &lt; 600]"/> 

    <xsl:template match="datarate"> 
     [<xsl:value-of select="@rate"/>] 
    </xsl:template> 
</xsl:stylesheet> 

Так как вам нужно, чтобы проверить, есть ли 600 и использовать 800 в качестве порогового значения, если нет 600 не найдено, вы могли бы это нравится:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text" encoding="UTF-8"/> 

    <xsl:variable name="threshold"> 
     <xsl:choose> 
      <xsl:when test="//datarate[@rate = 600]">600</xsl:when> 
      <xsl:otherwise>800</xsl:otherwise> 
     </xsl:choose> 
    </xsl:variable> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="//datarate"> 
      <xsl:sort select="@rate" data-type="number"/> 
     </xsl:apply-templates> 
    </xsl:template> 

    <xsl:template match="datarate[@rate &lt; $threshold]"/> 

    <xsl:template match="datarate"> 
     [<xsl:value-of select="@rate"/>] 
    </xsl:template> 
</xsl:stylesheet> 

в случае там может быть не ни 600, ни 800 вы можете добавить больше логики в $threshold против приемлемая декларация.

p.s. Не имея подробностей о том, как вы хотели бы построить свою строку, я только что напечатал значения @rate, заключенные в [].

0

Это короткое и простое преобразование (без явной команды условной используется на всех - не xsl:choose, нет xsl:when, нет xsl:otherwise):

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="/*"> 
    <t> 
    <xsl:apply-templates select="*"> 
    <xsl:sort select="@rate" data-type="number"/> 
    </xsl:apply-templates> 
    </t> 
</xsl:template> 

<xsl:template match= 
    "datarate 
    [not(@rate >= 600) 
    or 
     not(../*[@rate = 600]) and not(@rate >= 800) 
    ]"/> 
</xsl:stylesheet> 

при применении к предоставленному XML-документу (завернутый в один верхний элемент, который должен быть выполнен хорошо):

<t> 
    <datarate rate="200" /> 
    <datarate rate="600" /> 
    <datarate rate="300" /> 
    <datarate rate="400" /> 
    <datarate rate="800" /> 
    <datarate rate="1000" /> 
</t> 

производит желаемое, правильный результат:

<t> 
    <datarate rate="600"/> 
    <datarate rate="800"/> 
    <datarate rate="1000"/> 
</t> 

при нанесении на следующем, слегка измененный XML-документ (не скорость 600, но скорости 601 и 650):

<t> 
    <datarate rate="200" /> 
    <datarate rate="601" /> 
    <datarate rate="650" /> 
    <datarate rate="300" /> 
    <datarate rate="400" /> 
    <datarate rate="800" /> 
    <datarate rate="1000" /> 
</t> 

снова правильный результат получается:

<t> 
    <datarate rate="800"/> 
    <datarate rate="1000"/> 
</t> 
+0

приятно ... только когда вы меняете свой первый вход, чтобы иметь '650' вместо' 600', он распечатает его. Я понял оригинальные требования, так что если «600», новый порог «800». Вы должны будете иметь условное место где-то там :) не так ли? –

+0

Я понял, что если есть 600 и 800, тогда результат будет начинаться с 800. –

+0

@Pavel Veller: ОК, похоже, ваше понимание проблемы было правильным - я исправил ответ соответствующим образом. –

Смежные вопросы