关于xslt:有效地更新元素中的文本

Update text in an element - Effectively

我需要这里专家的帮助,以优化更新element中的字符串值的解决方案。我有这个xml文件作为输入...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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将是唯一的,并且可以交叉引用。 Q,T和G是上述请求中的ID。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?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个要编辑的位置的记录的效果如何。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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>

示例输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<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>

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
<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>