2013-09-03 3 views
1

Можно ли генерировать вывод, идентичный fn:analyze-string (XPath 3.0), используя xsl:analyze-string (XSLT 2.0)?Duplicate fn: analysis-string() вывод с использованием xsl: analysis-string?

Некоторые примеры для ввода строки abcdefg:

  1. regex="^a((b(c))d)(efg)$"

    <s:analyze-string-result xmlns:s="http://www.w3.org/2009/xpath-functions/analyze-string"> 
        <s:match>a<s:group nr="1"> 
         <s:group nr="2">b<s:group nr="3">c</s:group> 
         </s:group>d</s:group> 
         <s:group nr="4">efg</s:group> 
        </s:match> 
    </s:analyze-string-result> 
    
  2. regex="^((a(bc)d)(.*))$

    <s:analyze-string-result xmlns:s="http://www.w3.org/2009/xpath-functions/analyze-string"> 
        <s:match> 
         <s:group nr="1"> 
          <s:group nr="2">a<s:group nr="3">bc</s:group>d</s:group> 
          <s:group nr="4">efg</s:group> 
         </s:group> 
        </s:match> 
    </s:analyze-string-result> 
    
  3. regex="^(((a)(b)(cde)(.*)))$"

    <s:analyze-string-result xmlns:s="http://www.w3.org/2009/xpath-functions/analyze-string"> 
        <s:match> 
         <s:group nr="1"> 
          <s:group nr="2"> 
           <s:group nr="3">a</s:group> 
           <s:group nr="4">b</s:group> 
           <s:group nr="5">cde</s:group> 
           <s:group nr="6">fg</s:group> 
          </s:group> 
         </s:group> 
        </s:match> 
    </s:analyze-string-result> 
    

Я подозреваю, что это невозможно, потому что xsl:analyze-string не предоставляют методы для: 1) знать, как много групп там, или 2) открыть родитель/потомок групп для облегчения рекурсии. Но мне любопытно, есть ли что-то, что я забыл.

ответ

1

Вы можете сделать это немного проще, изменив синтаксис регулярных выражений, с помощью <g> </g> для группировки, а не () (это было бы возможно, но утомительно не делать этого, и вместо того, чтобы анализировать регулярное выражение и определить группы)

Как только у вас есть структура группы, вы можете сгенерировать нормальное регулярное выражение, используя (), чтобы перейти к xsl:analyze-function, добавив дополнительные группы, чтобы каждый текстовый прогон был сгруппирован и может быть получен позже с помощью regex-group().

Не подвергается обширной проверке, так что могут быть ошибки, но что-то вроде этого, и, похоже, это работает на ваших примерах.

<xsl:stylesheet version="2.0" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     xmlns:f="data:,f" 
     exclude-result-prefixes="xs" 
     > 

<xsl:output omit-xml-declaration="yes"/> 

<xsl:function name="f:analyze-string"> 
<xsl:param name="s"/> 
<xsl:param name="r"/> 
<xsl:variable name="rr"> 
    <xsl:apply-templates mode="a-s" select="$r"/> 
</xsl:variable> 
<xsl:text>&#10;</xsl:text> 
<f:analyze-string-result> 
    <xsl:text>&#10;</xsl:text> 
    <xsl:analyze-string select="$s" regex="{$rr}"> 
    <xsl:matching-substring> 
    <f:match> 
    <xsl:variable name="m" select="."/> 
    <xsl:apply-templates mode="g" select="$r"/> 
    </f:match> 
    <xsl:text>&#10;</xsl:text> 
    </xsl:matching-substring> 
    <xsl:non-matching-substring> 
    <f:non-match> 
    <xsl:value-of select="."/> 
    </f:non-match> 
    </xsl:non-matching-substring> 
    </xsl:analyze-string> 
    <xsl:text>&#10;</xsl:text> 
</f:analyze-string-result> 
<xsl:text>&#10;</xsl:text> 
</xsl:function> 

<xsl:template mode="a-s" match="g"> 
<xsl:text>(</xsl:text> 
<xsl:apply-templates mode="a-s"/> 
<xsl:text>)</xsl:text> 
</xsl:template> 

<xsl:template mode="a-s" match="text()[../g]"> 
<xsl:text>(</xsl:text> 
<xsl:value-of select="."/> 
<xsl:text>)</xsl:text> 
</xsl:template> 

<xsl:template mode="g" match="g"> 
<f:group> 
    <xsl:attribute name="nr"> 
    <xsl:number level="any"/> 
    </xsl:attribute> 
    <xsl:apply-templates mode="g"/> 
</f:group> 
</xsl:template> 

<xsl:template mode="g" match="text()"> 
<xsl:variable name="n"> 
    <xsl:number count="g|text()[../g]" level="any"/> 
</xsl:variable> 
<xsl:value-of select="regex-group(xs:integer($n))"/> 
</xsl:template> 

<xsl:template name="main"> 

<!-- regex="^a((b(c))d)(efg)$" --> 
<xsl:variable name="r">a<g><g>b<g>c</g></g>d</g><g>efg</g>$</xsl:variable> 
<xsl:sequence select="f:analyze-string('abcdefg',$r)"/> 

<!-- regex="^((a(bc)d)(.*))$ --> 
<xsl:variable name="r"><g><g>a<g>bc</g>d</g><g>.*</g></g>$</xsl:variable> 
<xsl:sequence select="f:analyze-string('abcdefg',$r)"/> 


<!-- regex="^(((a)(b)(cde)(.*)))$" --> 
<xsl:variable name="r"><g><g><g>a</g><g>b</g><g>cde</g><g>.*</g></g></g>$</xsl:variable> 
<xsl:sequence select="f:analyze-string('abcdefg',$r)"/> 


</xsl:template> 

</xsl:stylesheet> 

Производит

$ saxon9 -it main analyse.xsl 

<f:analyze-string-result xmlns:f="data:,f"> 
<f:match>a<f:group nr="1"><f:group nr="2">b<f:group nr="3">c</f:group></f:group>d</f:group><f:group nr="4">efg</f:group></f:match> 

</f:analyze-string-result> 

<f:analyze-string-result xmlns:f="data:,f"> 
<f:match><f:group nr="1"><f:group nr="2">a<f:group nr="3">bc</f:group>d</f:group><f:group nr="4">efg</f:group></f:group></f:match> 

</f:analyze-string-result> 

<f:analyze-string-result xmlns:f="data:,f"> 
<f:match><f:group nr="1"><f:group nr="2"><f:group nr="3">a</f:group><f:group nr="4">b</f:group><f:group nr="5">cde</f:group><f:group nr="6">fg</f:group></f:group></f:group></f:match> 

</f:analyze-string-result> 
Смежные вопросы