2015-09-05 2 views
0

Пожалуйста, предложите, как получить максимальное значение «rid» из всех внешних ссылок, кроме как из разделов «Онлайн». Определив максимальное значение «rid», необходимо вставить атрибут в те ссылки, которые выше до максимального значения. См. Текст требуемого результата.Как получить максимальный размер xref 'rid', за исключением определенного раздела

XML:

<article> 
<body> 
    <sec><title>Sections</title> 
    <p>The test <xref rid="b1">1</xref>, <xref rid="b2">2</xref>, <xref rid="b3 b4 b5">3-5</xref></p></sec> 
    <sec><title>Online</title><!--This section's xrefs no need to consider--> 
     <p>The test <xref rid="b6">6</xref></p> 
     <sec><title>Other</title> 
      <p><xref rid="b1">1</xref>, <xref rid="b7 b8">7-8</xref></p> 
     </sec> 
    </sec><!--This section's xrefs no need to consider--> 
    <sec> 
     <p>Final test test</p> 
     <sec><title>Third title</title><p>Last text</p></sec> 
    </sec> 
</body> 
<bm> 
    <ref id="b1">The ref01</ref> 
    <ref id="b2">The ref02</ref> 
    <ref id="b3">The ref03</ref> 
    <ref id="b4">The ref04</ref> 
    <ref id="b5">The ref05</ref> 
    <ref id="b6">The ref06</ref> 
    <ref id="b7">The ref07</ref> 
    <ref id="b8">The ref08</ref> 
</bm> 
</article> 

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

<xsl:variable name="var1"><!--Variable to get the all 'rid's except sec/title contains 'Online' --> 
    <xsl:for-each select="//xref[not(. is ancestor::sec[title[contains(., 'Online')]]/descendant-or-self)]/@rid"> 
    <!--xsl:for-each select="//xref/@rid[not(contains(ancestor::sec/title, 'Online'))]"--><!--for this xpath, error is : "XPTY0004: A sequence of more than one item is not allowed as the first argument" --> 
    <!--xsl:for-each select="//xref/@rid[not(contains(ancestor::sec[1]/title, 'Online')) and not(contains(ancestor::sec[2]/title, 'Online'))]"--><!--for this xpath we are getting the required result, but there may be several nesting of 'sec's --> 
     <xsl:choose> 
      <xsl:when test="contains(., ' ')"> 
       <xsl:for-each select="tokenize(., ' ')"> 
        <a><xsl:value-of select="."/></a> 
       </xsl:for-each> 
      </xsl:when> 
      <xsl:otherwise><a><xsl:value-of select="."/></a></xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
</xsl:variable> 
<xsl:variable name="varMax1"> 
    <xsl:for-each select="$var1/a"> 
     <xsl:sort select="substring-after(., 'b')" order="descending" data-type="number"/> 
     <a><xsl:value-of select="."/></a> 
    </xsl:for-each> 
</xsl:variable> 

<xsl:variable name="varMax"><!--Variable to get max valued RID --> 
    <xsl:value-of select="substring-after($varMax1/a[1], 'b')"/> 
</xsl:variable> 

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

<xsl:template match="ref"> 
    <xsl:variable name="varID"><xsl:value-of select="substring-after(@id, 'b')"/></xsl:variable> 
    <xsl:choose> 
     <xsl:when test="number($varMax) lt number($varID)"> 
      <xsl:copy> 
       <xsl:apply-templates select="@*"/> 
       <xsl:attribute name="MoveRef">yes</xsl:attribute> 
       <xsl:apply-templates select="node()"/> 
      </xsl:copy> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 
</xsl:stylesheet> 

Требуемый результат:

<article> 
<body> 
    <sec><title>Sections</title> 
    <p>The test <xref rid="b1">1</xref>, <xref rid="b2">2</xref>, <xref rid="b3 b4 b5">3-5</xref></p></sec> 
    <sec><title>Online</title><!--This section's xrefs no need to consider--> 
     <p>The test <xref rid="b6">6</xref></p> 
     <sec><title>Other</title> 
      <p><xref rid="b1">1</xref>, <xref rid="b7">7</xref>, <xref rid="b8">8</xref></p> 
     </sec> 
    </sec><!--This section's xrefs no need to consider--> 
    <sec> 
     <p>Final test test</p> 
     <sec><title>Third title</title><p>Last text</p></sec> 
    </sec> 
</body> 
<bm> 
    <ref id="b1">The ref01</ref> 
    <ref id="b2">The ref02</ref> 
    <ref id="b3">The ref03</ref> 
    <ref id="b4">The ref04</ref> 
    <ref id="b5">The ref05</ref> 
    <ref id="b6" MoveRef="yes">The ref06</ref> 
    <ref id="b7" MoveRef="yes">The ref07</ref> 
    <ref id="b8" MoveRef="yes">The ref08</ref> 
</bm> 
</article> 

Здесь рассмотрим номер 5 для «б 5 'rid, 6 для' b6 '.... (Потому что буквенно-цифровой)

ответ

1

Возможно, вы можете использовать другой подход, а не пытаться найти максимум rid атрибут, который не находится в разделе «онлайн». Не в последнюю очередь потому, что не совсем ясно, что такое максимум, когда вы имеете дело с буквенно-цифровой строкой.

Вместо этого вы могли бы определить ключ для поиска элементов в разделе «онлайн» по имени

<xsl:key name="online" match="sec[title = 'Online']//*" use="name()" /> 

А потом еще один ключ, чтобы посмотреть на xref элементы, которые встречаются в других разделах

<xsl:key name="other" match="xref[not(ancestor::sec/title = 'Online')]" use="name()" /> 

Затем вы можете написать шаблон по математике в ref элементы и использовать xsl:if, чтобы определить, следует ли добавить MoveRef к нему атрибут:

<xsl:variable name="id" select="@id" /> 
<xsl:if test="key('online', 'xref')[tokenize(@rid, ' ')[. = $id]] and not(key('other', 'xref')[tokenize(@rid, ' ')[. = $id]])"> 

Попробуйте это гораздо короче XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 
    <xsl:output method="xml" indent="yes" /> 

    <xsl:key name="online" match="sec[title = 'Online']//*" use="name()" /> 
    <xsl:key name="other" match="xref[not(ancestor::sec/title = 'Online')]" use="name()" /> 

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

    <xsl:template match="ref"> 
     <ref> 
      <xsl:variable name="id" select="@id" /> 
      <xsl:if test="key('online', 'xref')[tokenize(@rid, ' ')[. = $id]] and not(key('other', 'xref')[tokenize(@rid, ' ')[. = $id]])"> 
       <xsl:attribute name="MoveRef" select="'Yes'" /> 
      </xsl:if> 
      <xsl:apply-templates select="@*|node()"/> 
     </ref> 
    </xsl:template> 
</xsl:stylesheet> 

Вы можете фактически внести поправки в ref шаблон поставить условие в матче шаблона, если вы хотите ...

<xsl:template match="ref[key('online', 'xref')[tokenize(@rid, ' ')[. = current()/@id]] and not(key('other', 'xref')[tokenize(@rid, ' ')[. = current()/@id]])]"> 
    <ref MoveRef="Yes"> 
     <xsl:apply-templates select="@*|node()"/> 
    </ref> 
</xsl:template> 
+0

Спасибо за предложение, но если тип диапазона, например 7-8, то мы не получим требуемый результат. –

+0

@ RudramuniTP - Я исправил свой ответ, чтобы справиться с этой ситуацией. Возможно, стоит изменить ваш вопрос, чтобы показать пример '' в вашем XML. Спасибо. –

+0

Большое спасибо за ваше идеальное предложение, отлично работающее по мере необходимости. Плюс один... –

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