在XPath中提取以下兄弟节点的子节点属性

时间:2017-11-12 14:35:55

标签: xml xslt xpath

我的XML代码是,

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<unit
   xmlns="http://www.srcML.org/srcML/src" revision="0.9.5" language="Java" filename="ListSample.java">
<class>
    <specifier>public</specifier> class 
    <name>ListSample</name>
    <block>{

        <decl_stmt>
            <decl>
                <specifier>private</specifier>
                <type>
                    <name>List</name>
                </type>
                <name>nameList</name>
                <init>=
                    <expr>
                        <operator>new</operator>
                        <call>
                            <name>List</name>
                            <argument_list>()</argument_list>
                        </call>
                    </expr>
                </init>
            </decl>;
        </decl_stmt>
        <function>
            <specifier>public</specifier>
            <type>
                <name>void</name>
            </type>
            <name>method</name>
            <parameter_list>()</parameter_list>
            <block>{

                <expr_stmt>
                    <expr>
                        <call>
                            <name>
                                <name>nameList</name>
                                <operator>.</operator>
                                <name>add</name>
                            </name>
                            <argument_list>(
                                <argument>
                                    <expr>
                                        <literal type="string">"name"</literal>
                                    </expr>
                                </argument>)
                            </argument_list>
                        </call>
                    </expr>;
                </expr_stmt>
                }
            </block>
        </function>
        }
    </block>
</class>

我正在尝试提取任何List的数据类型。例如, nameList 是XML文件中给出的列表。我试图通过搜索列表的名称(以List关键字开头),然后通过确定 literal type =&#34; string&#34; 中的数据类型来实现此目的。这是我的代码使用XPath和XSLT。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:template
    match="//*[local-name()='name'][preceding-sibling::node()='List']">
    <xsl:variable name="listName" select="text()"></xsl:variable>
    <xsl:call-template name="getType">
        <xsl:with-param name="listName" select="$listName" />
    </xsl:call-template>

</xsl:template>
<xsl:template name="getType"
    match="//*[local-name()='name'][following-sibling::node()='.' and following-sibling::node()[2]='add']">
    <xsl:param name="listName" />
    <xsl:if test="node()=$listName">
        <xsl:message>
            <xsl:value-of select="parent::node()/following-sibling::literal/@type" />
        </xsl:message>
    </xsl:if>

</xsl:template>

但是,消息中包含的部分

<xsl:message>
    <xsl:value-of select="parent::node()/following-sibling::literal/@type" />
</xsl:message>

无法获取文字类型。如何更正代码以便我可以获取属性中的文字节点和数据类型?提前致谢。

2 个答案:

答案 0 :(得分:4)

我仍然不确定这是什么目的,但这会产生预期的结果:

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

  <!-- key to locate the usage of a list in an .add() operation based on the list 
       variable's name -->      
  <xsl:key name="kListUsage"
           match="src:call[src:name[src:operator[1] = '.' and src:name[2] = 'add']]"
           use="src:name/src:name[1]" />

  <!-- Override default handling of text nodes -->
  <xsl:template match="text()" />

  <xsl:template match="src:decl[src:type/src:name = 'List']/src:name">
    <xsl:apply-templates select="key('kListUsage', .)[1]" mode="listUsage" />
  </xsl:template>

  <xsl:template match="src:call" mode="listUsage">
    <xsl:message>
      <xsl:value-of select="src:argument_list/src:argument[1]/src:expr/src:literal/@type"/>
    </xsl:message>
  </xsl:template>
</xsl:stylesheet>

在样本输入上运行时,会输出以下消息:

string

除此之外,如果您考虑到他们与共享祖先相对应的位置并从这些共享祖先处理下来,那么当逻辑变得更清晰时,您似乎将重点放在节点相对于彼此的位置上。

答案 1 :(得分:1)

鉴于您当前的XPath,需要进行一些调整:

  1. /unit/class/block/decl_stmt/decl/type/name元素中,您需要跳过两个级别。父级是type,您想要升级到decl元素
  2. decl元素开始,以下兄弟是function元素,它将具有literal后代
  3. 您的XML绑定到命名空间,并且您选择literal元素,就像绑定到&#34; no命名空间&#34;,因此请调整以按local-name()选择在其他领域完成
  4. 更新的XPath,它产生&#34; string&#34;在消息中:

    parent::*/parent::node()/following-sibling::*//*[local-name()='literal']/@type"
    

    您也可以这样写:

    ../../following-sibling::*//*[local-name()='literal']/@type
    

    您可以只使用following::轴并更简洁地写一下:

    ../../following::*[local-name()='literal']/@type