XSLT - 循环

时间:2015-05-18 17:22:41

标签: xslt

我正面临生产中的一个问题,我希望您能帮助我们了解XSLT代码更改的最佳选择。 我有以下源结构需要在我的中间件中进行转换:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:SMRESULTS xmlns:ns0="http://www.mycompany.com/SYS/SCENARIO/VERSION">
   <ns0:PREAMBLE>
      <ns0:I_SITE_CODE/>
      <ns0:I_DESTINATION/>
      <ns0:I_FILENAME/>
      <ns0:I_RECORD_TYPE/>
   </ns0:PREAMBLE>
   <ns0:SAMPLES>
      <ns0:SAMPLE>
         <ns0:S_APPROVAL_REASON/>
         <ns0:D_TANK_CONFORMITY/>
         <ns0:D_SAMPLE>
            <ns0:D_SAMPLE_ID/>
            <ns0:D_SAMPLE_VALUE/>
         </ns0:D_SAMPLE>
         <ns0:TESTS>
            <ns0:TEST>
               <ns0:T_ANALYSIS/>
               <ns0:T_AUTHORISATION_COMMENT/>
               <ns0:D_TEST>
                  <ns0:D_TEST_ID/>
                  <ns0:D_TEST_VALUE/>
               </ns0:D_TEST>
               <ns0:RESULTS>
                  <ns0:RESULT>
                     <ns0:R_VALUE/>
                     <ns0:D_GRDB_PROPERTY/>
                     <ns0:D_RESULT>
                        <ns0:D_RESULT_ID/>
                        <ns0:D_RESULT_VALUE/>
                     </ns0:D_RESULT>
                  </ns0:RESULT>
               </ns0:RESULTS>
            </ns0:TEST>
         </ns0:TESTS>
      </ns0:SAMPLE>
   </ns0:SAMPLES>
</ns0:SMRESULTS>

我的要求是每当“&lt;”找到符号(特征D_RESULT_ID ='Sm.Result.Min_Limit'和D_RESULT_VALUE = <![CDATA[<=600.0000]]> 该值必须转移到'Sm.Result.Max_Limit'特征,并且必须消除特征'Sm.Result.Min_Limit'。

举例说明:对于以下源数据......

<?xml version="1.0" encoding="ISO-8859-1" ?>
   <SMRESULTS  xmlns="http://www.mycompany.com/SYS/SCENARIO/VERSION" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <PREAMBLE>
         <I_SITE_CODE>Site Code</I_SITE_CODE>
         <I_DESTINATION>Destination</I_DESTINATION>
         <I_FILENAME>filename.zzz</I_FILENAME>
         <I_RECORD_TYPE>INSERT</I_RECORD_TYPE>
      </PREAMBLE>
      <SAMPLES>
         <SAMPLE>
            <S_APPROVAL_REASON></S_APPROVAL_REASON>
            <D_TANK_CONFORMITY></D_TANK_CONFORMITY>
            <D_SAMPLE>
               <D_SAMPLE_ID>Sm.Sample.BatchId</D_SAMPLE_ID>
               <D_SAMPLE_VALUE></D_SAMPLE_VALUE>
            </D_SAMPLE>
            <D_SAMPLE>
               <D_SAMPLE_ID>Sm.Sample.Type</D_SAMPLE_ID>
               <D_SAMPLE_VALUE></D_SAMPLE_VALUE>
            </D_SAMPLE>
            <D_SAMPLE>
               <D_SAMPLE_ID>SM.Sample.Template_ID</D_SAMPLE_ID>
               <D_SAMPLE_VALUE>SPEP-PE</D_SAMPLE_VALUE>
            </D_SAMPLE>
            <TESTS>
               <TEST>
                  <T_ANALYSIS>AnalysisCode</T_ANALYSIS>
                  <D_TEST>
                     <D_TEST_ID>Sm.Test.DerivedGRDBTestMethod</D_TEST_ID>
                     <D_TEST_VALUE></D_TEST_VALUE>
                  </D_TEST>
                  <RESULTS>
                     <RESULT  xsi:nil="false">
                        <R_VALUE>0.000</R_VALUE>
                        <D_GRDB_PROPERTY></D_GRDB_PROPERTY>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.DerivedGRDBUOM</D_RESULT_ID>
                           <D_RESULT_VALUE></D_RESULT_VALUE>
                        </D_RESULT>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.Min_Limit</D_RESULT_ID>
                           <D_RESULT_VALUE></D_RESULT_VALUE>
                        </D_RESULT>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.Max_Limit</D_RESULT_ID>
                           <D_RESULT_VALUE></D_RESULT_VALUE>
                        </D_RESULT>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.FailedCriticalLvl</D_RESULT_ID>
                           <D_RESULT_VALUE>false</D_RESULT_VALUE>
                        </D_RESULT>
                     </RESULT>
                     <RESULT  xsi:nil="false">
                        <R_VALUE>0.000</R_VALUE>
                        <D_GRDB_PROPERTY></D_GRDB_PROPERTY>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.DerivedGRDBUOM</D_RESULT_ID>
                           <D_RESULT_VALUE></D_RESULT_VALUE>
                        </D_RESULT>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.Min_Limit</D_RESULT_ID>
                           <D_RESULT_VALUE></D_RESULT_VALUE>
                        </D_RESULT>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.Max_Limit</D_RESULT_ID>
                           <D_RESULT_VALUE></D_RESULT_VALUE>
                        </D_RESULT>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.FailedCriticalLvl</D_RESULT_ID>
                           <D_RESULT_VALUE>false</D_RESULT_VALUE>
                        </D_RESULT>
                     </RESULT>
                     <RESULT  xsi:nil="false">
                        <R_VALUE>344.712</R_VALUE>
                        <D_GRDB_PROPERTY>ASH</D_GRDB_PROPERTY>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.DerivedGRDBUOM</D_RESULT_ID>
                           <D_RESULT_VALUE>59W</D_RESULT_VALUE>
                        </D_RESULT>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.Min_Limit</D_RESULT_ID>
                           <D_RESULT_VALUE><![CDATA[<=600.0000]]></D_RESULT_VALUE>
                        </D_RESULT>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.Max_Limit</D_RESULT_ID>
                           <D_RESULT_VALUE></D_RESULT_VALUE>
                        </D_RESULT>
                        <D_RESULT>
                           <D_RESULT_ID>Sm.Result.FailedCriticalLvl</D_RESULT_ID>
                           <D_RESULT_VALUE>false</D_RESULT_VALUE>
                        </D_RESULT>
                     </RESULT>
                  </RESULTS>
               </TEST>
            </TESTS>
         </SAMPLE>
      </SAMPLES>
   </SMRESULTS>

......期望的结果应如下:

...
            <RESULT>
              <R_VALUE>344.712</R_VALUE>
              <D_GRDB_PROPERTY>ASH</D_GRDB_PROPERTY>
              <D_RESULT>
                <D_RESULT_ID>Sm.Result.DerivedGRDBUOM</D_RESULT_ID>
                <D_RESULT_VALUE>59W</D_RESULT_VALUE>
              </D_RESULT>
              <D_RESULT>
                <D_RESULT_ID>Sm.Result.Min_Limit</D_RESULT_ID>
                <D_RESULT_VALUE/>
              </D_RESULT>
              <D_RESULT>
                <D_RESULT_ID>Sm.Result.Max_Limit</D_RESULT_ID>
                <D_RESULT_VALUE><![CDATA[<=600.0000]]></D_RESULT_VALUE>
              </D_RESULT>
              <D_RESULT>
                <D_RESULT_ID>Sm.Result.FailedCriticalLvl</D_RESULT_ID>
                <D_RESULT_VALUE>false</D_RESULT_VALUE>
              </D_RESULT>
            </RESULT>
...

我必须在当前的XSLT中进行调整,如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http://www.mycompany.com/SYS/SCENARIO/VERSION" xmlns:map="java:java.util.Map" xmlns:dyn="java:com.sap.aii.mapping.api.DynamicConfiguration" xmlns:key="java:com.sap.aii.mapping.api.DynamicConfigurationKey" xmlns:javamap="java:package.xi.common.util.DateConversion">
    <xsl:output method="xml" encoding="ISO-8859-1" indent="yes"/>
    <xsl:param name="inputparam"/>
    <xsl:param name="Region">
        <xsl:text>UTC</xsl:text>
    </xsl:param>
    <xsl:param name="DateTimeFormat">
        <xsl:text>yyyyMMdd_HHmmss</xsl:text>
    </xsl:param>
    <xsl:param name="DYNAMIC_CONFIG_NS_FILE">
        <xsl:text>http://sap.com/xi/XI/System/File</xsl:text>
    </xsl:param>
    <xsl:param name="DYNAMIC_CONFIG_KEY">
        <xsl:text>FileName</xsl:text>
    </xsl:param>
    <xsl:param name="SampleID">
        <xsl:value-of select="a:SMRESULTS/a:SAMPLES/a:SAMPLE/a:S_ID_NUMERIC"/>
    </xsl:param>
    <!-- Call the getCurrentDateTime function from Global Services.-->
    <xsl:param name="CurrentDateTime">
        <xsl:if test="function-available('javamap:getCurrentDateTime')">
            <xsl:value-of select="javamap:getCurrentDateTime($Region, $DateTimeFormat)"/>
        </xsl:if>
    </xsl:param>
    <xsl:param name="DynFileName">
        <xsl:value-of select="concat($SampleID,'_',$CurrentDateTime,'.xml')"/>
    </xsl:param>
    <!-- Set File Name in Dynamic Configuration.-->
    <xsl:variable name="DynamicConf" select="map:get($inputparam, 'DynamicConfiguration')"/>
    <xsl:variable name="DynamicKey" select="key:create($DYNAMIC_CONFIG_NS_FILE, $DYNAMIC_CONFIG_KEY)"/>
    <xsl:variable name="FileName" select="dyn:put($DynamicConf, $DynamicKey, $DynFileName)"/>

    <xsl:template match="/">
        <SMRESULTS xmlns="http://www.mycompany.com/SYS/SCENARIO/VERSION">
            <PREAMBLE>
                <I_SITE_CODE>
                    <xsl:value-of select="a:SMRESULTS/a:PREAMBLE/a:I_SITE_CODE"/>
                </I_SITE_CODE>
                <I_DESTINATION>
                    <xsl:value-of select="a:SMRESULTS/a:PREAMBLE/a:I_DESTINATION"/>
                </I_DESTINATION>
                <I_FILENAME>
                    <xsl:value-of select="a:SMRESULTS/a:PREAMBLE/a:I_FILENAME"/>
                </I_FILENAME>
                <I_RECORD_TYPE>
                    <xsl:value-of select="a:SMRESULTS/a:PREAMBLE/a:I_RECORD_TYPE"/>
                </I_RECORD_TYPE>
            </PREAMBLE>
            <SAMPLES>
                <SAMPLE>
                    <S_APPROVAL_REASON>
                        <xsl:value-of select="a:SMRESULTS/a:SAMPLES/a:SAMPLE/a:S_APPROVAL_REASON"/>
                    </S_APPROVAL_REASON>
                    <D_TANK_CONFORMITY>
                        <xsl:value-of select="a:SMRESULTS/a:SAMPLES/a:SAMPLE/a:D_TANK_CONFORMITY"/>
                    </D_TANK_CONFORMITY>
                    <xsl:for-each select="/a:SMRESULTS/a:SAMPLES/a:SAMPLE/a:D_SAMPLE">
                        <D_SAMPLE>
                            <D_SAMPLE_ID>
                                <xsl:value-of select="a:D_SAMPLE_ID"/>
                            </D_SAMPLE_ID>
                            <D_SAMPLE_VALUE>
                                <xsl:value-of select="a:D_SAMPLE_VALUE"/>
                            </D_SAMPLE_VALUE>
                        </D_SAMPLE>
                    </xsl:for-each>
                    <TESTS>
                        <xsl:for-each select="a:SMRESULTS/a:SAMPLES/a:SAMPLE/a:TESTS/a:TEST">
                            <TEST>
                                <T_ANALYSIS>
                                    <xsl:value-of select="a:T_ANALYSIS"/>
                                </T_ANALYSIS>
                                <T_AUTHORISATION_COMMENT>
                                    <xsl:value-of select="a:T_AUTHORISATION_COMMENT"/>
                                </T_AUTHORISATION_COMMENT>
                                <xsl:for-each select="a:D_TEST">
                                    <D_TEST>
                                        <D_TEST_ID>
                                            <xsl:value-of select="a:D_TEST_ID"/>
                                        </D_TEST_ID>
                                        <D_TEST_VALUE>
                                            <xsl:value-of select="a:D_TEST_VALUE"/>
                                        </D_TEST_VALUE>
                                    </D_TEST>
                                </xsl:for-each>
                                <RESULTS>
                                    <xsl:for-each select="a:RESULTS/a:RESULT">
                                        <RESULT>
                                            <R_VALUE>
                                                <xsl:value-of select="a:R_VALUE" disable-output-escaping="yes"/>
                                            </R_VALUE>
                                            <D_GRDB_PROPERTY>
                                                <xsl:value-of select="a:D_GRDB_PROPERTY" disable-output-escaping="yes"/>
                                            </D_GRDB_PROPERTY>
                                            <xsl:for-each select="a:D_RESULT">
                                                <D_RESULT>
                                                    <D_RESULT_ID>
                                                        <xsl:value-of select="a:D_RESULT_ID"/>
                                                    </D_RESULT_ID>
                                                    <D_RESULT_VALUE>
                                                        <xsl:value-of select="a:D_RESULT_VALUE"/>
                                                    </D_RESULT_VALUE>
                                                </D_RESULT>
                                            </xsl:for-each>
                                        </RESULT>
                                    </xsl:for-each>
                                </RESULTS>
                            </TEST>
                        </xsl:for-each>
                    </TESTS>
                </SAMPLE>
            </SAMPLES>
        </SMRESULTS>
    </xsl:template>
</xsl:stylesheet>

我删除了一些不必要的直接映射字段,只是为了缩短它。

任何意见/建议都将不胜感激!

谢谢!

1 个答案:

答案 0 :(得分:0)

你现有的转变是可怕的。你有同情心。

尽管如此,您应该能够通过修改<D_RESULT_VALUE>元素内容的模板片段来实现您描述的行为,与您在其他问题中提供的解决方案相同。这是更新的样式表的相关片段(比实际更改略宽,以便使XPath表达式的上下文清晰;还有,缩进):

<xsl:for-each select="a:D_RESULT">
    <D_RESULT>
        <D_RESULT_ID>
            <xsl:value-of select="a:D_RESULT_ID"/>
        </D_RESULT_ID>
        <D_RESULT_VALUE>
            <xsl:choose>
                <xsl:when test="a:D_RESULT_ID='Sm.Result.Max_Limit' and ../a:D_RESULT[a:D_RESULT_ID='Sm.Result.Min_Limit'][contains(a:D_RESULT_VALUE, '&lt;')]">
                  <xsl:value-of select="../a:D_RESULT[a:D_RESULT_ID='Sm.Result.Min_Limit']/a:D_RESULT_VALUE"/>
                </xsl:when>
                <xsl:when test="a:D_RESULT_ID='Sm.Result.Min_Limit' and contains(., '&lt;')"/>
                <xsl:otherwise>
                    <xsl:value-of select="a:D_RESULT_VALUE"/>
                </xsl:otherwise>
            </xsl:choose>
        </D_RESULT_VALUE>
    </D_RESULT>
</xsl:for-each>

我没有任何方法可以通过较小的改变来做你想做的事。

请注意,此模板片段假定除了<RESULT> <D_RESULT>之外,需要修改的任何D_RESULT_ID='Sm.Result.Min_Limit'元素还包含另一个<D_RESULT> D_RESULT_ID='Sm.Result.Max_Limit'复制前者的<D_RESULT_VALUE>。如果不是这种情况,则转换将简单地丢弃Min_Limit值。

此外,当Min_Limit值复制到Max_Limit时,Max_Limit的任何先前值都会无可挽回地丢失(但据我所知,这是{s} s你想要的是什么。