максимальное значение атрибута - PullRequest
2 голосов
/ 21 октября 2010

Я хочу изменить значения @page атрибутов <line/>, которые являются потомками от <section type="cover"/> до (max(@page) + 1) из <section type="contents"/>.

В основном мне нужно, чтобы номер страницы для раздела обложки был на 1 больше, чем последний числовой номер страницы раздела содержимого.

Примечание: <line/> узлы не всегда являются братьями и сестрами, они могут быть вложены на любом уровне.

Например, преобразовать это:

<root>
    <section type="contents">
        <line page="i">text</line> 
        <line page="ii">text</line> 
        <line page="1">text</line> 
        <line page="1">text</line> 
        <line page="2">text</line>
        <block>
            <line page="3">text</line> 
            <line page="4">text</line> 
        </block>
    </section>
    <section type="cover">
        <line page="i">text</line> 
        <line page="i">text</line> 
    </section>
</root>

к этому:

<root>
    <section type="contents">
        <line page="i">text</line> 
        <line page="ii">text</line> 
        <line page="1">text</line> 
        <line page="1">text</line> 
        <line page="2">text</line>
        <block>
            <line page="3">text</line> 
            <line page="4">text</line> 
        </block>
    </section>
    <section type="cover">
        <line page="5">text</line> <!-- @page changes to max()+1 -->
        <line page="5">text</line> <!-- @page changes to max()+1 -->
    </section>
</root>

Есть ли простой способ добиться этого с помощью PHP5, XSLT1.0, XPATH?

1 Ответ

2 голосов
/ 21 октября 2010

Это преобразование :

<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:variable name="vMax">
      <xsl:for-each select="/*/*//line/@page">
       <xsl:sort data-type="number"/>
       <xsl:if test="position() = last()">
         <xsl:value-of select="."/>
       </xsl:if>
      </xsl:for-each>
    </xsl:variable>

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

 <xsl:template match="section[@type='cover']/line/@page">
  <xsl:attribute name="page">
   <xsl:value-of select="$vMax+1"/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному XML-документу :

<root>
    <section type="contents">
        <line page="i">text</line>
        <line page="ii">text</line>
        <line page="1">text</line>
        <line page="1">text</line>
        <line page="2">text</line>
        <block>
            <line page="3">text</line>
            <line page="4">text</line>
        </block>
    </section>
    <section type="cover">
        <line page="i">text</line>
        <line page="i">text</line>
    </section>
</root>

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

<root>
   <section type="contents">
      <line page="i">text</line>
      <line page="ii">text</line>
      <line page="1">text</line>
      <line page="1">text</line>
      <line page="2">text</line>
      <block>
         <line page="3">text</line>
         <line page="4">text</line>
      </block>
   </section>
   <section type="cover">
      <line page="5">text</line>
      <line page="5">text</line>
   </section>
</root>

Примечание : требуемый максимум получается с помощью сортировки по атрибуту page всех элементов line и взятия pageатрибут последнего элемента в отсортированном наборе узлов.

В XSLT 1.0 для всех практических целей этот способ нахождения максимума или минимума является самым быстрым , хотя он имеет сложность:O (N * log (N)), в то время как есть O (N) алгоритмов.Все дело в константе ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...