Как увеличить глобальную переменную при чтении моего конкретного тега с помощью xslt2.0? - PullRequest
1 голос
/ 28 сентября 2011

Это мой XML-документ.

<w:document xmlns:w="w">
 <w:body>
   <w:p>
        <w:r>
           <w:t>
               Para1
            </w:t>
        </w:r>
     </w:p>
   <w:p>
        <w:r>
           <w:t>
               Para2
            </w:t>
        </w:r>
     </w:p>
   <w:p>
        <w:r>
           <w:t>
               Para3
            </w:t>
        </w:r>
     </w:p>
   <w:p>
        <w:r>
           <w:t>
               Para4
            </w:t>
        </w:r>
     </w:p>
   <w:p>
        <w:r>
           <w:t>
               Para5
            </w:t>
        </w:r>
     </w:p>

   <w:tbl>
         <w:tr>
            <w:tc>
               <w:p>
                  <w:r>
                    <w:t>
                         Para6
                    </w:t>
                   </w:r>
                </w:p>
              </w:tc>
            <w:tc>
               <w:p>
                  <w:r>
                    <w:t>
                         Para7 
                    </w:t>
                   </w:r>
                </w:p>
              </w:tc>
           </w:tr>
        </w:tbl>
     <w:p>
        <w:r>
           <w:t>
               Para8
            </w:t>
        </w:r>
     </w:p>
  <w:tbl>
         <w:tr>
            <w:tc>
               <w:p>
                  <w:r>
                    <w:t>
                         Para9
                    </w:t>
                   </w:r>
                </w:p>
              </w:tc>
            <w:tc>
               <w:p>
                  <w:r>
                    <w:t>
                         Para10
                    </w:t>
                   </w:r>
                </w:p>
              </w:tc>
           </w:tr>
        </w:tbl>
    <w:p>
        <w:r>
           <w:t>
               Para11
            </w:t>
        </w:r>
     </w:p>
</w:body>
</w:document>

Теперь я хочу увеличивать свою глобальную переменную всякий раз, когда <w:tbl><w:tr> встречает. Для моего вышеупомянутого xml-файла он имеет два <w:tr> узла внутри <w:tbl>.

So, for example :  
                1. if my current node is Para8 then it's count will be 1.
                2. if my current node is para11 then it's count will be 2.
   

Как мне это сделать?

1 Ответ

2 голосов
/ 28 сентября 2011

XSLT - это функциональный язык, и на любом функциональном языке значение переменной, одного набора, не может быть обновлено . Нужен «сдвиг парадигмы» - чтобы начать думать функционально - чтобы понять, что «способность» обновлять переменные вовсе не нужна. Для любого императивного алгоритма (который использует обновление переменной) существует соответствующий функциональный алгоритм (который не требует обновления какой-либо переменной).

Использование функционального стиля программирования по сравнению с императивным имеет ряд преимуществ - главное в том, что функциональную программу гораздо лучше читать, понимать, поддерживать и даже доказывать правильность. Поскольку переменные являются неизменяемыми, оптимизатор компилятора может выполнять гораздо более агрессивную оптимизацию, что приводит к более эффективным, высоко оптимизированным скомпилированным программам.

В этом конкретном случае нет необходимости обновлять переменную для получения необходимого количества :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:w="w">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:for-each select=
      "//w:t
         [contains(., 'Para8')
         or
          contains(., 'Para11')
         ]
     ">
       <xsl:number level="any" count="w:tbl/w:tr"/>
       <xsl:text>&#xA;</xsl:text>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML :

 <w:document xmlns:w="w">
    <w:body>
        <w:p>
            <w:r>
                <w:t>                Para1             </w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:r>
                <w:t>                Para2             </w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:r>
                <w:t>                Para3             </w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:r>
                <w:t>                Para4             </w:t>
            </w:r>
        </w:p>
        <w:p>
            <w:r>
                <w:t>                Para5             </w:t>
            </w:r>
        </w:p>
        <w:tbl>
            <w:tr>
                <w:tc>
                    <w:p>
                        <w:r>
                            <w:t>                          Para6                     </w:t>
                        </w:r>
                    </w:p>
                </w:tc>
                <w:tc>
                    <w:p>
                        <w:r>
                            <w:t>                          Para7                      </w:t>
                        </w:r>
                    </w:p>
                </w:tc>
            </w:tr>
        </w:tbl>
        <w:p>
            <w:r>
                <w:t>                Para8             </w:t>
            </w:r>
        </w:p>
        <w:tbl>
            <w:tr>
                <w:tc>
                    <w:p>
                        <w:r>
                            <w:t>                          Para9                     </w:t>
                        </w:r>
                    </w:p>
                </w:tc>
                <w:tc>
                    <w:p>
                        <w:r>
                            <w:t>                          Para10                     </w:t>
                        </w:r>
                    </w:p>
                </w:tc>
            </w:tr>
        </w:tbl>
        <w:p>
            <w:r>
                <w:t>                Para11             </w:t>
            </w:r>
        </w:p>
    </w:body>
</w:document>

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

1
2

В случае, если это значение должно содержаться в переменной - для последующего использования где-нибудь в ее области видимости, переменная будет просто определяться как :

 <xsl:variable name="vMyCount">
   <xsl:number level="any" count="w:tbl/w:tr"/>
 </xsl:variable>

И вы можете использовать эту переменную как в приведенном ниже преобразовании:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:w="w">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
     <xsl:for-each select=
      "//w:t
         [contains(., 'Para5')
         or
          contains(., 'Para8')
         or
          contains(., 'Para11')
         ]
     ">
     <xsl:variable name="vMyCount">
       <xsl:number level="any" count="w:tbl/w:tr"/>
     </xsl:variable>
     <xsl:value-of select=
      "concat($vMyCount,
              substring('0', 1 + boolean(string($vMyCount)))
              )"/>
       <xsl:text>&#xA;</xsl:text>
     </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

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

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