2

我有以下 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>

我想转换成这个输出:

derived
    D1

base
    B1

请注意,节点/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>

这可行(使用 Notepad++ 中的 XML 工具插件),但not(//type[name=current()/../../superType]/properties/property[name=current()/name])XPath 表达式效率极低:当应用于 200K 行 XML 文件时,转换需要280 秒。如果没有这个 XPath 表达式,转换只需要2 秒

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

4

2 回答 2

1

测量这个速度...

<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>  
于 2012-11-15T02:50:50.510 回答
1

加速它的最简单方法是使用优化的 XSLT 处理器 - Saxon-EE 应该将此表达式视为可以从哈希索引中受益的表达式,将其从 O(n^2) 变为 O(n)。

按照 Durkin 的建议,下一个最佳方法是使用键对其进行手动优化。

于 2012-11-15T11:08:58.257 回答