首页 文章

XSLT如何在模板匹配中使用通配符

提问于
浏览
0

我试图在匹配中实现一种通配符机制,以便在XSLT模板中使用 .
我最初的问题是我在一组文件中寻找java代码行 . 我正在寻找的线路可能是这样的:

a.setValue(2);
System.out.println(a.toString());
a.getValue();

在这一行中, a 不是确切的变量名,而是一种占位符 . 我正在寻找三个java代码行,其中以这种方式使用相同的变量 .
为了实现我的目标,我想到了使用XSLT,因为有了它我想解释这种概念 .
srcml我在xml中翻译了java代码,这是我需要查找java代码行的xml表 .

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<unit filename="Users/bibi/Documents/UniMi/CloudStation/TesiM/DSL/DSL/resources/src/src_beautified/strategy/StrategyExample.java" language="Java" revision="0.9.5" xmlns="http://www.srcML.org/srcML/src">
<package>package 
    <name>strategy</name>
    ;</package>
<import>import 
    <name>
        <name>strategy</name>
        <operator>.</operator>
        <name>strategy</name>
        <operator>.</operator>
        <name>HelloWorld</name></name>;</import>
<import>import 
    <name>
        <name>strategy</name>
        <operator>.</operator>
        <name>strategy</name>
        <operator>.</operator>
        <name>SubArray</name></name>;</import>
<class>
    <specifier>public</specifier>class 
    <name>StrategyExample</name>
    <block>
        {

        <function>
            <specifier>public</specifier>
            <specifier>static</specifier>
            <type>
                <name>void</name></type>
            <name>main</name>
            <parameter_list>(
                <parameter>
                    <decl>
                        <type>
                            <name>
                                <name>String</name>
                                <index>[]</index></name>
                        </type>
                        <name>args</name>
                    </decl>
                </parameter>)</parameter_list>
            <block>{

                <decl_stmt>
                    <decl>
                        <type>
                            <name>MyArray</name></type>
                        <name>m</name>
                        <init>= 
                            <expr>
                                <operator>new</operator>
                                <call>
                                    <name>MyArray</name>
                                    <argument_list>
                                        (
                                        <argument>
                                            <expr>
                                                <literal type="number">10</literal></expr>
                                        </argument>)</argument_list>
                                </call>
                            </expr>
                        </init>
                    </decl>;</decl_stmt>
                <decl_stmt>
                    <decl>
                        <type>
                            <name>HelloWorld</name>
                        </type>
                        <name>hw</name>
                        <init>= 
                            <expr>
                                <operator>new</operator>
                                <call>
                                    <name>HelloWorld</name>
                                    <argument_list>()</argument_list></call>
                            </expr>
                        </init>
                    </decl>;</decl_stmt>
                <expr_stmt>
                    <expr>
                        <call>
                            <name>
                                <name>System</name>
                                <operator>.</operator>
                                <name>out</name>
                                <operator>.</operator>
                                <name>println</name>
                            </name>
                            <argument_list>(
                                <argument>
                                    <expr>
                                        <call>
                                            <name>
                                                <name>hw</name>
                                                <operator>.</operator>
                                                <name>getString</name></name>
                                            <argument_list>(
                                                <argument>
                                                    <expr>
                                                        <literal type="string">&quot;prova&quot;</literal></expr>
                                                </argument>)</argument_list>
                                        </call>
                                        <operator>.</operator>
                                        <call>
                                            <name>substring</name>
                                            <argument_list>(
                                                <argument>
                                                    <expr>
                                                        <literal type="number">0</literal></expr>
                                                </argument>, 
                                                <argument>
                                                    <expr>
                                                        <literal type="number">3</literal></expr>
                                                </argument>)</argument_list>
                                        </call>
                                    </expr>
                                </argument>)</argument_list>
                        </call>
                    </expr>;</expr_stmt>
                <expr_stmt>
                    <expr>
                        <call>
                            <name>
                                <name>m</name>
                                <operator>.</operator>
                                <name>setValue</name>
                            </name>
                            <argument_list>(
                                <argument>
                                    <expr>
                                        <literal type="number">1</literal></expr>
                                </argument>, 
                                <argument>
                                    <expr>
                                        <literal type="number">6</literal></expr>
                                </argument>)</argument_list>
                        </call>
                    </expr>;</expr_stmt>
                <expr_stmt>
                    <expr>
                        <call>
                            <name>
                                <name>m</name>
                                <operator>.</operator>
                                <name>setValue</name>
                            </name>
                            <argument_list>(
                                <argument>
                                    <expr>
                                        <literal type="number">0</literal></expr>
                                </argument>, 
                                <argument>
                                    <expr>
                                        <literal type="number">8</literal></expr>
                                </argument>)</argument_list>
                        </call>
                    </expr>;</expr_stmt>
                <expr_stmt>
                    <expr>
                        <call>
                            <name>
                                <name>hw</name>
                                <operator>.</operator>
                                <name>getString</name>
                            </name>
                            <argument_list>(
                                <argument>
                                    <expr>
                                        <operator>new</operator>
                                        <call>
                                            <name>String</name>
                                            <argument_list>
                                                (
                                                <argument>
                                                    <expr>
                                                        <literal type="string">&quot;ciao&quot;</literal></expr>
                                                </argument>)</argument_list>
                                        </call>
                                    </expr>
                                </argument>)</argument_list>
                        </call>
                    </expr>;</expr_stmt>
                }</block>
        </function>}</block>
</class>

在这个例子中,我想寻找这两行:

m.setValue( 1 , 6 );
m.setValue( 0 , 8 );

我为了捕获这一行而生成的xslt模板中使用的xpath匹配是这样的:

src:expr_stmt
[src:expr[src:call[src:name[src:operator='.'][src:name='setValue']]
[src:argument_list
[src:argument[src:expr[src:literal='1'][src:literal[contains(@type, 'number')]]]]
[src:argument[src:expr[src:literal='6'][src:literal[contains(@type, 'number')]]]]]]]
[following-sibling::*[2][self::src:expr_stmt
[src:expr[src:call[src:name[src:name[matches(@name, preceding-sibling::*[2]/@src_expr/src_call/src_name/src:name)]
[src:operator='.'][src:name='setValue']]
[src:argument_list[src:argument[src:expr[src:literal='0'][src:literal[contains(@type, 'number')]]]]
[src:argument[src:expr[src:literal='8'][src:literal[contains(@type, 'number')]]]]]]]]]]

但它无法正常工作,因为它选择了所有 src:expr_stmt 节点 .
有谁能够帮我?

2 回答

  • 1

    如果我现在正确理解你的要求,我认为密钥有助于解决这个问题 . 这是你提供的后一个例子的XSLT(带有两个 .setValue ):

    <xsl:stylesheet version="1.0"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                    xmlns:src="http://www.srcML.org/srcML/src">
      <xsl:output method="xml" indent="yes"/>
    
      <!-- key for first statement pattern -->    
      <xsl:key name="expr1"
               match="src:expr_stmt[src:expr/src:call[
                          src:name[src:operator = '.' and src:name[2] = 'setValue']
                          and
                          src:argument_list[
                              src:argument[1]/src:expr/src:literal = 1 and
                              src:argument[2]/src:expr/src:literal = 6
                          ]
                      ]]"
               use="src:expr/src:call/src:name/src:name[1]"
       />
      <!-- key for second statement pattern -->
      <xsl:key name="expr2"
               match="src:expr_stmt[src:expr/src:call[
                          src:name[src:operator = '.' and src:name[2] = 'setValue']
                          and
                          src:argument_list[
                              src:argument[1]/src:expr/src:literal = 0 and
                              src:argument[2]/src:expr/src:literal = 8
                          ]
                      ]]"
               use="src:expr/src:call/src:name/src:name[1]"
       />
    
    
    
      <xsl:template match="text()" />
    
      <xsl:template match="/">
        <n>
          <xsl:apply-templates/>
        </n>
      </xsl:template>
    
      <!-- breakdown of this expression:
           count(key('N', path)) = count(. | key('N', path)) -> the current node is in key N
    
           (the current node is in key expr1 OR
            the current node is in key expr2) 
           AND
           there is a node in key expr1 for the current node's first src:name 
           AND
           there is a node in key expr2 for the current node's first src:name
      -->
      <xsl:template match="src:expr_stmt[(count(key('expr1', src:expr/src:call/src:name/src:name[1])) = 
                                          count(. | key('expr1', src:expr/src:call/src:name/src:name[1])) or
                                          count(key('expr2', src:expr/src:call/src:name/src:name[1])) = 
                                          count(. | key('expr2', src:expr/src:call/src:name/src:name[1]))) 
                                         and
                                         key('expr1', src:expr/src:call/src:name/src:name[1]) 
                                         and 
                                         key('expr2', src:expr/src:call/src:name/src:name[1])]">
        <xsl:copy-of select="." />
      </xsl:template>
    
    </xsl:stylesheet>
    

    在示例XML上运行时,输出为:

    <?xml version="1.0" encoding="utf-8"?>
    <n xmlns:src="http://www.srcML.org/srcML/src">
      <expr_stmt xmlns="http://www.srcML.org/srcML/src">
        <expr>
          <call>
            <name>
              <name>m</name>
              <operator>.</operator>
              <name>setValue</name>
            </name>
            <argument_list>
              (
              <argument>
                <expr>
                  <literal type="number">1</literal>
                </expr>
              </argument>,
              <argument>
                <expr>
                  <literal type="number">6</literal>
                </expr>
              </argument>)
            </argument_list>
          </call>
        </expr>;
      </expr_stmt>
      <expr_stmt xmlns="http://www.srcML.org/srcML/src">
        <expr>
          <call>
            <name>
              <name>m</name>
              <operator>.</operator>
              <name>setValue</name>
            </name>
            <argument_list>
              (
              <argument>
                <expr>
                  <literal type="number">0</literal>
                </expr>
              </argument>,
              <argument>
                <expr>
                  <literal type="number">8</literal>
                </expr>
              </argument>)
            </argument_list>
          </call>
        </expr>;
      </expr_stmt>
    </n>
    
  • 2

    我不确定我是否已经理解了这个问题,我认为如果你发布了一个简化的输入样本会更好,但我不能真正尝试将问题讨论成评论我将这个分组建议作为讨论贡献发布:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        exclude-result-prefixes="xs"
        xpath-default-namespace="http://www.srcML.org/srcML/src"
        version="2.0">
    
        <xsl:output indent="yes"/>
    
        <xsl:template match="/">
            <xsl:for-each-group select="//expr_stmt[expr/call/name[name]]" group-by="expr/call/name/name">
                <variable name="{current-grouping-key()}">
                    <xsl:for-each select="current-group()">
                        <statement>
                            <xsl:value-of select="normalize-space()"/>
                        </statement>                    
                    </xsl:for-each>
                </variable>
            </xsl:for-each-group>
        </xsl:template>
    
    </xsl:stylesheet>
    

    当我针对发布的输入样本运行此操作时,我会添加一些结束标记

    <variable name="m">
       <statement>m . printString ( @ CallBehavior ( id = "mf-getFormatType-0" , behavior = "MathFormat.getFormatType.String[]" ) { @ CallAction ( id = "main-mf.getFormatType-callActionExpr0" ) { mf . getFormatType () }}) ;</statement>
       <statement>m . printString ( @ CallBehavior ( id = "m-printString-2" , behavior = "MyArray.printString.String[String-]" ) { @ CallAction ( id = "main-m.printString-callActionExpr1" ) { m . printString ( "ciao" ) }}) . length () ;</statement>
       <statement>m . setValue ( 1 , 6 ) ;</statement>
       <statement>m . setValue ( 0 , 8 ) ;</statement>
       <statement>m . setValue ( 4 , 1 ) ;</statement>
       <statement>m . setValue ( 9 , 7 ) ;</statement>
       <statement>m . getValue ( j ) ;</statement>
       <statement>m . setValue ( j , j + 1 ) ;</statement>
    </variable>
    <variable name="printString">
       <statement>m . printString ( @ CallBehavior ( id = "mf-getFormatType-0" , behavior = "MathFormat.getFormatType.String[]" ) { @ CallAction ( id = "main-mf.getFormatType-callActionExpr0" ) { mf . getFormatType () }}) ;</statement>
       <statement>m . printString ( @ CallBehavior ( id = "m-printString-2" , behavior = "MyArray.printString.String[String-]" ) { @ CallAction ( id = "main-m.printString-callActionExpr1" ) { m . printString ( "ciao" ) }}) . length () ;</statement>
    </variable>
    <variable name="MyArray">
       <statement>MyArray . printValue () ;</statement>
    </variable>
    <variable name="printValue">
       <statement>MyArray . printValue () ;</statement>
    </variable>
    <variable name="setValue">
       <statement>m . setValue ( 1 , 6 ) ;</statement>
       <statement>m . setValue ( 0 , 8 ) ;</statement>
       <statement>m . setValue ( 4 , 1 ) ;</statement>
       <statement>m . setValue ( 9 , 7 ) ;</statement>
       <statement>m . setValue ( j , j + 1 ) ;</statement>
    </variable>
    <variable name="getValue">
       <statement>m . getValue ( j ) ;</statement>
    </variable>
    

    这至少看起来是解决问题的一步吗?可能是那些了解复杂输入格式的人可以进一步调整XPath或分组,但也许建议显示如何提取和分组格式中的某些元素 .

    比如说

    <xsl:template match="/">
        <xsl:for-each-group select="//expr_stmt[expr/call/name[name]]" group-by="expr/call/name/name[1]">
            <variable name="{current-grouping-key()}">
                <xsl:for-each select="current-group()">
                    <statement>
                        <xsl:value-of select="normalize-space()"/>
                    </statement>                    
                </xsl:for-each>
            </variable>
        </xsl:for-each-group>
    </xsl:template>
    

    我们只得到

    <variable name="m">
       <statement>m . printString ( @ CallBehavior ( id = "mf-getFormatType-0" , behavior = "MathFormat.getFormatType.String[]" ) { @ CallAction ( id = "main-mf.getFormatType-callActionExpr0" ) { mf . getFormatType () }}) ;</statement>
       <statement>m . printString ( @ CallBehavior ( id = "m-printString-2" , behavior = "MyArray.printString.String[String-]" ) { @ CallAction ( id = "main-m.printString-callActionExpr1" ) { m . printString ( "ciao" ) }}) . length () ;</statement>
       <statement>m . setValue ( 1 , 6 ) ;</statement>
       <statement>m . setValue ( 0 , 8 ) ;</statement>
       <statement>m . setValue ( 4 , 1 ) ;</statement>
       <statement>m . setValue ( 9 , 7 ) ;</statement>
       <statement>m . getValue ( j ) ;</statement>
       <statement>m . setValue ( j , j + 1 ) ;</statement>
    </variable>
    <variable name="MyArray">
       <statement>MyArray . printValue () ;</statement>
    </variable>
    

    要么

    <xsl:template match="/">
        <xsl:for-each-group select="//expr_stmt
            [expr[call[name[operator='.'][name='setValue']]
            [argument_list
            [argument[expr[literal= (1, 0)][literal[contains(@type, 'number')]]]]
            [argument[expr[literal= (6, 8)][literal[contains(@type, 'number')]]]]]]]" group-by="expr/call/name/name[1]">
            <variable name="{current-grouping-key()}">
                <xsl:for-each select="current-group()">
                    <statement>
                        <xsl:value-of select="normalize-space()"/>
                    </statement>                    
                </xsl:for-each>
            </variable>
        </xsl:for-each-group>
    </xsl:template>
    

    会给

    <variable name="m">
       <statement>m . setValue ( 1 , 6 ) ;</statement>
       <statement>m . setValue ( 0 , 8 ) ;</statement>
    </variable>
    

相关问题