Обновить текст в элементе - эффективно - PullRequest
1 голос
/ 30 марта 2011

Мне нужна помощь экспертов, чтобы оптимизировать решение обновления строкового значения в элементе. У меня есть этот XML-файл в качестве входных данных ...

<?xml version="1.0" encoding="UTF-8"?>
<FullRequest>
    <Header>
        <Looptimes>3</Looptimes>
        <SomeElement>blah!</SomeElement>
        <AnotherElement>blah!!</AnotherElement>
    </Header>
    <RequestDetail>
        <!-- Request Element is a string of fixed length (50 characters) -->
        <Request>THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG AGAIN!</Request>
        <Request>THE TIME FOX JUMPED OVER THE LAZY DOG, PROGRESSED!</Request>
        <Request>OWING TO THE WIDESPREAD KNOWLEDGE OF THE PHRASE AN</Request>
    </RequestDetail>
</FullRequest>

Смещение 5 в элементе Request будет уникальным и может иметь перекрестные ссылки. Q, T и G - идентификаторы в вышеуказанном запросе.

<?xml version="1.0" encoding="UTF-8"?>
<FullResponse>
    <Header>
        <Looptimes>3</Looptimes>
        <SomeElement>blah!</SomeElement>
        <AnotherElement>blah!!</AnotherElement>
    </Header>
    <ResponseDetail>
        <!-- Response element repeats for 3 times as indicated by the value of Looptimes -->
        <!-- Id has a unique value -->
        <Response>
            <Id>Q</Id>
            <Value1>ABC</Value1>
            <Value2>XYZ</Value2>
            <Value3>FGK</Value3>
        </Response>
        <Response>
            <Id>T</Id>
            <Value1>123</Value1>
            <Value2>YOK</Value2>
            <Value3>DSL</Value3>
        </Response>
        <Response>
            <Id>G</Id>
            <Value1>BAT</Value1>
            <Value2>TKR</Value2>
            <Value3>LAF</Value3>
        </Response>
    </ResponseDetail>
</FullResponse>

Принимая вышеупомянутый xml, позиции смещения 10, 15 и 20 должны быть заменены значениями Value1, Value2 и Value3 соответственно.

У меня есть этот XSL, который делает эту работу. Не уверен, насколько хорошо это решение будет работать с несколькими тысячами записей по 5000 символов в каждой (50 символов в элементе «Запрос», показанном здесь в качестве примера) с около 20 местами для редактирования.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:regexp="http://exslt.org/regular-expressions" exclude-result-prefixes="regexp">
    <xsl:output omit-xml-declaration="no" indent="yes"/>
    <xsl:preserve-space elements="*"/>

    <xsl:variable name="WebResponse" select="document('local:///ic1-data.xml')"/>
    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*"/>
        </xsl:copy>

    </xsl:template>

    <xsl:template match="/FullRequest/RequestDetail/Request">
        <xsl:variable name="currentLine" select="."/>
        <xsl:variable name="id" select="substring($currentLine,5,1)"/>
        <xsl:for-each select="$WebResponse/FullResponse/ResponseDetail/Response">
            <xsl:variable name="ResId" select="Id"/>

            <xsl:if test="$id = $ResId">
                <xsl:element name="{name()}">
                    <!-- Update Value1 -->
                    <xsl:variable name="from" select="substring($currentLine,10,3)"/>
                    <xsl:variable name="UpdatedValue1"
                        select="regexp:replace($currentLine,$from,'',Value1)"/>

                    <!-- Update Value2 -->
                    <xsl:variable name="from2" select="substring($UpdatedValue1,15,3)"/>
                    <xsl:variable name="UpdatedValue2"
                        select="regexp:replace($UpdatedValue1,$from2,'',Value2)"/>

                    <!-- Update Value3 -->
                    <xsl:variable name="from3" select="substring($UpdatedValue2,20,3)"/>
                    <xsl:value-of select="regexp:replace($UpdatedValue2,$from3,'',Value3)"/>
                </xsl:element>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Пример вывода будет следующим:

<?xml version="1.0" encoding="UTF-8"?>
<FullRequest>
    <Header>
        <Looptimes>3</Looptimes>
        <SomeElement>blah!</SomeElement>
        <AnotherElement>blah!!</AnotherElement>
    </Header>
    <RequestDetail>
        <Response>THE QUICKABCOWXYZOXFGKMPS OVER THE LAZY DOG AGAIN!</Response>
        <Response>THE TIME 123 JYOKEDDSLER THE LAZY DOG, PROGRESSED!</Response>
        <Response>OWING TO BAT WTKRSPLAFD KNOWLEDGE OF THE PHRASE AN</Response>
    </RequestDetail>
</FullRequest>

Я могу использовать только XSLT 1.0

Можете ли вы предложить, как сделать это лучше?

Спасибо.

1 Ответ

1 голос
/ 30 марта 2011

Еще один более гибкий подход:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:key name="kResponseById" match="Response" use="Id"/>
    <xsl:variable name="WebResponse" select="document('ic1-data.xml')"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Request/text()">
        <xsl:variable name="vCurrent" select="."/>
        <xsl:for-each select="$WebResponse">
            <xsl:call-template name="replace">
                <xsl:with-param name="pString" select="$vCurrent"/>
                <xsl:with-param name="pValues"
                     select="key('kResponseById',
                                 substring($vCurrent,5,1)
                             )/*[starts-with(local-name(),'Value')]"/>
            </xsl:call-template>
        </xsl:for-each>
    </xsl:template>
    <xsl:template name="replace">
        <xsl:param name="pString"/>
        <xsl:param name="pValues"/>
        <xsl:choose>
            <xsl:when test="$pValues">
                <xsl:variable name="pLimit"
                    select="substring-after(
                               local-name($pValues[1]),
                               'Value'
                            ) * 5 + 4"/>
                <xsl:call-template name="replace">
                    <xsl:with-param name="pString"
                         select="concat(
                                    substring($pString, 1, $pLimit),
                                    $pValues[1],
                                    substring($pString, $pLimit + 4)
                                 )"/>
                    <xsl:with-param name="pValues"
                         select="$pValues[position()!=1]"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$pString"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<FullRequest>
    <Header>
        <Looptimes>3</Looptimes>
        <SomeElement>blah!</SomeElement>
        <AnotherElement>blah!!</AnotherElement>
    </Header>
    <RequestDetail>
        <!-- Request Element is a string of fixed length (50 characters) -->
        <Request>THE QUICKABCOWXYZOXFGKMPS OVER THE LAZY DOG AGAIN!</Request>
        <Request>THE TIME 123 JYOKEDDSLER THE LAZY DOG, PROGRESSED!</Request>
        <Request>OWING TO BAT WTKRSPLAFD KNOWLEDGE OF THE PHRASE AN</Request>
    </RequestDetail>
</FullRequest>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...