оптимизироватьсо многими - PullRequest
0 голосов
/ 13 июля 2010

У меня есть серия XML-документов среднего размера, которые в основном представляют собой текст с несколькими узлами, представляющими макросы, подлежащие расширению, например ::10000

<foo>Some text <macro>A1</macro> ... <macro>B2</macro> ...etc...</foo>

Моя цель - заменить каждый макрос на соответствующий XML. Обычно это один тег <img> с разными атрибутами, но это может быть и другой HTML.

Таблица стилей генерируется программно, и один из способов сделать это - иметь шаблон для каждого макроса, например

<xsl:template match="macro[.='A1']">
    <!-- content goes here -->
</xsl:template>
<xsl:template match="macro[.='A2']">
    <!-- other content goes here -->
</xsl:template>
<xsl:template match="macro[.='B2']">
    <!-- etc... -->
</xsl:template>

Работает просто отлично, но может иметь до ста макросов и не очень производительно (я использую libxslt.) Я попробовал пару альтернатив, таких как:

<xsl:template match="macro">
    <xsl:choose>
        <xsl:when test=".='A1'">
            <!-- content goes here -->
        </xsl:when>
        <xsl:when test=".='A2'">
            <!-- other content goes here -->
        </xsl:when>
        <xsl:when test=".='B2'">
            <!-- etc... -->
        </xsl:when>
    </xsl:choose>
</xsl:template>

Это немного более производительно. Я попытался добавить еще один уровень ветвления, например:

<xsl:template match="macro">
    <xsl:choose>
        <xsl:when test="substring(.,1,1) = 'A'">
            <xsl:choose>
                <xsl:when test=".='A1'">
                    <!-- content goes here -->
                </xsl:when>
                <xsl:when test=".='A2'">
                    <!-- other content goes here -->
                </xsl:when>
            </xsl:choose>
        </xsl:when>
        <xsl:when test=".='B2'">
            <!-- etc... -->
        </xsl:when>
    </xsl:choose>
</xsl:template>

Он загружается немного медленнее (XSL больше и немного сложнее), но работает немного быстрее (каждая ветвь может исключить несколько случаев.)

Теперь мне интересно, есть ли лучший способ сделать это? У меня около 50-100 макросов. Обычно преобразование выполняется с использованием libxslt, но я не могу использовать проприетарные расширения других движков XSLT.

Любые входные данные приветствуются:)

Ответы [ 3 ]

1 голос
/ 13 июля 2010

Попробуйте извлечь всю обработку macro в отдельный шаблонный режим и запустить ее только для содержимого элемента macro. I.e.:

<xsl:template match="macro">
   <xsl:apply-templates mode="macro"/>
</xsl:template>

<xsl:temlate match="text()[. = 'A1']" mode="macro">
   ...
</xsl:template>

Я подозреваю, что замедление в вашем случае связано с тем, что ваши правила проверяются один за другим для каждого входного узла. Таким образом, вы получаете один чек, чтобы увидеть, является ли он macro, и только если это так, контент сопоставляется дальше.

1 голос
/ 13 июля 2010

Это может быть другим способом:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
    <xsl:variable name="dummy">
            <mac id="A1">success</mac>
            <mac id="A2">fail</mac>
            <mac id="B1">This <b>fail</b></mac>
            <mac id="B2">This <b>success</b></mac>
    </xsl:variable>
    <xsl:key name="macro" match="mac" use="@id"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="macro">
        <xsl:variable name="me" select="."/>
        <xsl:for-each select="document('')">
            <xsl:copy-of select="key('macro',$me)/node()"/>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Примечание : это была производительность: синтаксический анализ XML 1805мс, синтаксический анализ XSL 0,483мс, преобразование 0,215мс

1 голос
/ 13 июля 2010

Если ваши макросы имеют фиксированный XML, у вас может быть документ macros.xml, который выглядит примерно так:

<?xml version="1.0"?>
<macros>
    <macro name="A1"><!-- content goes here --></macro>
    <macro name="A2"><!-- content goes here --></macro>
</macros>

Затем вы можете иметь:

<xsl:template match="macro">
    <xsl:variable name="name" select="text()"/>
    <xsl:apply-templates select="document(macros.xml)/macros/macro[@name=$name]" mode="copy"/>
</xsl:template>

<xsl:template match="*" mode="copy">
    <xsl:copy><xsl:copy-of select="*"/>
        <xsl:apply-templates mode="copy"/>
    </xsl:copy>
</xsl:template>

Улучшает ли этопроизводительность

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...