Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
XSLT:有效地测试a';表亲';节点存在_Xslt_Xpath_Xslt 1.0 - Fatal编程技术网

XSLT:有效地测试a';表亲';节点存在

XSLT:有效地测试a';表亲';节点存在,xslt,xpath,xslt-1.0,Xslt,Xpath,Xslt 1.0,我有以下XML: <types> <type> <name>derived</name> <superType>base</superType> <properties> <property> <name>B1</name> </prop

我有以下XML:

<types>
    <type>
        <name>derived</name>
        <superType>base</superType>
        <properties>
            <property>
                <name>B1</name>
            </property>
            <property>
                <name>D1</name>
            </property>
        </properties>
    </type>
    <type>
        <name>base</name>
        <properties>
            <property>
                <name>B1</name>
            </property>
        </properties>
    </type>
</types>
请注意,已跳过节点
/types/type[name='derived']/properties/property[name='B1']
,因为它在基类型中的形式为:
/types/type[name='base']/properties/property[name='B1']

我提出了以下XSLT:

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

    <!-- Do nothing for base class properties -->
    <!-- Wouldn't be necessary if the match criteria could be applied in the select -->
    <xsl:template match="property"/>

    <xsl:template match="property[not(//type[name=current()/../../superType]/properties/property[name=current()/name])]">
        <xsl:text>&#x09;</xsl:text>
        <xsl:value-of select="name"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

    <xsl:template match="types/type">
        <xsl:value-of select="name"/>
        <xsl:text>&#10;</xsl:text>
        <xsl:apply-templates select="./properties"/>
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

</xsl:stylesheet>
这是可行的(使用记事本++中的XML工具插件),但是
不是(//type[name=current()/../../superType]/properties/properties[name=current()/name])
XPath表达式的效率非常低:当应用于一个200K行的XML文件时,转换需要280秒。如果没有此XPath表达式,转换只需2秒


有什么方法可以加快速度吗?

测量一下速度

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

<xsl:key name="kPropertyByName" match="property" use="name" /> 

<xsl:template match="property">
  <xsl:variable name="supertype" select="../../superType/text()" />
  <xsl:if test="($supertype = '') or not ( key('kPropertyByName',name)/../../name[.=$supertype])">
    <xsl:value-of select="concat('&#x09;',name,'&#x0A;')" /> 
  </xsl:if>  
</xsl:template>  

<xsl:template match="type">
  <xsl:value-of select="concat(name,'&#x0A;')" />
  <xsl:apply-templates select="properties" />
  <xsl:text>&#x0A;</xsl:text>
</xsl:template>  

</xsl:stylesheet>  

提高速度的最简单方法是使用优化的XSLT处理器——Saxon EE应该发现这个表达式可以从哈希索引中获益,将它从O(n^2)转换为O(n)


第二个最好的方法是按照Durkin的建议,使用键手动优化它。

您确定使用的是XSLT 1.0处理器吗?在XSLT 1.0中,模式中不允许使用
current()。。。在一台现代个人电脑上,要比阿波罗号的飞行计算机进行更多的计算,才能把人们带到月球上和带回来。要提高性能,你可以做的一件事是使用更明确的路径(即
/types/type
,而不是
/type
)。否则,处理器将被迫遍历树中的每个节点,搜索
类型
元素。@Mads:同意这将在一定程度上加快速度;但是对于遍历树的每个节点:从概念上讲,可能是这样,但是好的处理器(例如Saxon)会在有利的时候按名称索引元素。因此,一个
//foo
表达式并不像一个简单的实现那样昂贵。@DevNull:好问题。XMLTools插件不做XSLT,只做XPath,因此OP显然通过将其作为XPath表达式应用来测试其匹配模式。谢谢-这将时间缩短到了~7秒,这对于我来说足够快了。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>
<xsl:strip-space elements="*"/>

<xsl:key name="kPropertyByName" match="property" use="name" /> 

<xsl:template match="property">
  <xsl:variable name="supertype" select="../../superType/text()" />
  <xsl:if test="($supertype = '') or not ( key('kPropertyByName',name)/../../name[.=$supertype])">
    <xsl:value-of select="concat('&#x09;',name,'&#x0A;')" /> 
  </xsl:if>  
</xsl:template>  

<xsl:template match="type">
  <xsl:value-of select="concat(name,'&#x0A;')" />
  <xsl:apply-templates select="properties" />
  <xsl:text>&#x0A;</xsl:text>
</xsl:template>  

</xsl:stylesheet>