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)に変換する必要があります。

次善の方法は、ダーキンが提案したように、キーを使用して手動で最適化することです。

于 2012-11-15T11:08:58.257 に答える