2011-03-29 36 views
1

我需要專家的幫助來優化元素中更新字符串值的解決方案。我有這個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在請求元素將是唯一的,並且可以交叉引用。 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,需要分別用值Value1,Value2和Value3替換偏移位置10,15和20。

我有這個工作的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

另一種更靈活的方法是:

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

+1不錯的辦法。 – Flack 2011-03-30 05:49:04

+0

太棒了!智能解決方案在示例場景中,您已經很好地使用了一些對稱的偏移位置。我想實際的東西會是隨機的。我將嘗試使用建議的方法進行處理。再一次感謝你。 – Liv2luv 2011-03-30 19:00:52

+0

@ Liv2luv:不客氣。如果偏移量不符合公式,則可以使用內聯或外部地圖。或者,如果偏移函數比映射更復雜,則可以在將模板應用於'ValueN'元素時使用模式匹配。 – 2011-03-30 19:36:32