更新元素中的文本 - 实际上

时间:2011-03-29 20:55:35

标签: xslt

我需要专家的帮助来优化更新元素中字符串值的解决方案。我有这个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>

Request元素中的Offset 5将是唯一的,可以交叉引用。 Q,T和G是上述请求中的ID。

<?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个字符的记录(这里显示的Request元素中有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 个答案:

答案 0 :(得分:1)

另一种更灵活的方法是:

<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>