XSLT:有效测试 'cousin' 节点是否存在

标签 xslt xpath xslt-1.0

我有以下 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='categories']/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工具插件),但是不行(//type[name=current()/../../superType]/properties/property[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:有效测试 'cousin' 节点是否存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13389163/

相关文章:

java - 在java中如何根据字符串过滤出xml中的子节点

php - 使用 PHP 从 DOM 节点而不是其子节点获取内容

xslt - 如何使用来自其他节点的计算数据汇总节点

xml - 仅在 xslt 中对单例标签进行模式匹配

XSLT、循环中的多个 XML 文件、命名空间问题

css - 如何使用 Cypress 从 react 下拉列表中进行选择

xml - XSLT 1.0 : IDOC to AdsML transformation

xslt - if 条件与字符串长度

java - 使用XSLT解析XML时如何处理多个小数?

python - 如何使用 python lxml 通过 xslt 加速大型 xml 文件的转换