Bonjour tout le monde,

J'ai de gros problèmes de performances avec la fonction XMLType.transform, qui sert à appliquer un XSL sur un XML...

Lorsque le XML est relativement gros, cette fonction est très très lente, et en plus, elle consomme tout le CPU pour elle (empêchant les autres utilisateurs de travailler...).

Et pourtant, le même XSL appliqué au même gros XML via un autre transformer XSL (par exemple oraxsl et même Internet Explorer sur mon PC) se fait de façon quasi instantanée...

Ci-dessous un exemple reproductible...

Avez-vous une idée?

Merci d'avance.

Nicolas.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
 
/* Formatted on 2006/02/09 16:56 (Formatter Plus v4.8.5) */
DECLARE
  v_xsl      CLOB
    := '
<!-- ================================================================================ -->
<!--                                                                                  -->
<!-- Feuille de style utilisée pour importer un fichier XML dans l''application        -->
<!--                                                                                  -->
<!-- Création  : PAN 2006.01.16                                                       -->
<!-- Drn Modif : PAN 2006.01.18, Traitement des quotes dans les valeurs               -->
<!--                                                                                  -->
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" encoding="iso-8859-1"/>
 
  <!-- ================================================================================ -->
  <!-- Template qui double les quotes d''un message                                      -->
  <!-- ================================================================================ -->
  <xsl:template name="trt_dblApo">
    <xsl:param name="p_txt"/>
    <xsl:choose>
      <xsl:when test=''contains($p_txt,"&apos;")''>
        <!-- Il y a au moins une quote dans le texte -->
        <xsl:value-of select=''concat(substring-before($p_txt,"&apos;"), "&apos;&apos;")'' />
        <xsl:call-template name="trt_dblApo">
          <xsl:with-param name="p_txt" select=''substring-after($p_txt,"&apos;")'' />
        </xsl:call-template>  
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$p_txt"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
 
  <!-- ================================================================================ -->
  <!-- Template appliqué à la racine                                                    -->
  <!-- ================================================================================ -->
	<xsl:template match="PRS">
      <xsl:choose>
 
        <xsl:when test="/PRS/STA/COD = ''ERR''">
          qms$errors.show_message(''MGC-00013'',
                      ''<xsl:call-template name="trt_dblApo">
                          <xsl:with-param name="p_txt" select="/PRS/STA/MSG"/>
                      </xsl:call-template>'');
        </xsl:when>
 
        <xsl:when test="count(//AFL) = 0">
          NULL;
        </xsl:when>
 
        <xsl:otherwise>
          <xsl:apply-templates/>
        </xsl:otherwise>
 
      </xsl:choose>
	</xsl:template>
 
  <!-- ================================================================================ --> 
  <!-- Template appliqué aux noeuds "Affilié"                                           --> 
  <!-- ================================================================================ --> 
  <xsl:template match="/PRS/AFL"> 
    <xsl:variable name="ligCou"> 
      <xsl:value-of select="./@LIGNUM"/>
    </xsl:variable>
    <xsl:apply-templates>
      <xsl:with-param name="p_lignum">
      <xsl:value-of select="$ligCou" /> 
      </xsl:with-param>
    </xsl:apply-templates>
  </xsl:template>
 
  <!-- ================================================================================ --> 
  <!-- Template appliqué aux noeuds "Affilié"                                           --> 
  <!-- ================================================================================ --> 
  <xsl:template match="AFL//*"> 
    <xsl:param name="p_lignum"/> 
 
    <xsl:choose>
      <xsl:when test="child::*">
        <!-- Le noeud courant a au moins un enfant, on applique les templates sur ceux-ci -->
        <xsl:apply-templates>
          <xsl:with-param name="p_lignum" select="$p_lignum"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:when test="not( child::* )">
        <!-- Le noeud courant n''a pas d''enfants, on génère du PLSQL -->
        <xsl:variable name="v_col">
          <xsl:call-template name="trt_dblApo">
            <xsl:with-param name="p_txt" select="name(.)"/>
          </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="v_val">
          <xsl:call-template name="trt_dblApo">
            <xsl:with-param name="p_txt" select="."/>
          </xsl:call-template>
        </xsl:variable>
        <b>(<xsl:value-of select="$p_lignum" />,''<xsl:value-of select="$v_col" />'',''<xsl:value-of select="$v_val" />'');</b>
      </xsl:when>
    </xsl:choose>
 
  </xsl:template>
 
  <!-- ================================================================================ -->
  <!-- Template appliqué aux noeuds texte par défaut                                    -->
  <!-- ================================================================================ -->
  <xsl:template match="text()">
    <!-- Ne rien faire, dérogation à la règle par défaut -->
  </xsl:template>
 
</xsl:stylesheet>
';
  v_xml0     CLOB := '<PRS>';
  v_xml1     CLOB
    := '
    <AFL LIGNUM="1999">
        <mat>20000001683</mat>
        <name>DOE</name>
        <firstname>JOHN</firstname>
        <name2>JACK</name2>
        <SEX>MALE</SEX>
        <birthday>1970-05-06</birthday>
        <salary>5236</salary>
        <code1>5</code1>
        <code2>6</code2>
        <code3>7</code3>
        <date>2006-05-06</date>
        <dsp>8.665</dsp>
        <dsp_2000>455.45</dsp_2000>
        <darr04>5.3</darr04>
        <darvap04>6</darvap04>
        <rcrr>8</rcrr>
        <rcrvap>9</rcrvap>
        <rcrvav>10</rcrvav>
        <rinet>11.231</rinet>
        <rmrr>12</rmrr>
        <rmrvap>14</rmrvap>
        <ro>15</ro>
        <rr>189</rr>
        <date2>2004-05-09</date2>
    </AFL>';
  v_xml2     CLOB
    := '
	  <STA>
        <COD>TER</COD>
        <MSG>Opération Réussie</MSG>
      </STA>
    </PRS>';
  v_xml      CLOB;
  v_return   CLOB;
BEGIN
  v_xml := v_xml0;
  v_xml := v_xml || v_xml1;
  v_xml := v_xml || v_xml2;
  -- On crée un petit XML, puis on le transforme avec la fonction Oracle XMLTYPE.transform()
  DBMS_OUTPUT.put_line (   'Before XMLTYPE.transform with a little XML: '
                        || TO_CHAR (SYSDATE, 'hh:mi:ss'));
  v_return := XMLTYPE (v_xml).transform (XMLTYPE (v_xsl)).getclobval ();
  v_return := REPLACE (v_return, '&apos;', '''');
  DBMS_OUTPUT.put_line (   'After XMLTYPE.transform with a little XML: '
                        || TO_CHAR (SYSDATE, 'hh:mi:ss'));
  DBMS_OUTPUT.put_line (SUBSTR (v_return, 1, 255));
  -- Ce résultat est obtenu très vite...
  --
  --
  -- Ici, on crée un gros XML...
  v_xml := v_xml0;
 
  FOR idx IN 1 .. 500
  LOOP
    v_xml := v_xml || v_xml1;
  END LOOP;
 
  v_xml := v_xml || v_xml2;
  -- On crée un GROS XML, puis on le transforme avec la fonction Oracle XMLTYPE.transform()
  DBMS_OUTPUT.put_line (   'Before XMLTYPE.transform with a BIG XML: '
                        || TO_CHAR (SYSDATE, 'hh:mi:ss'));
  v_return := XMLTYPE (v_xml).transform (XMLTYPE (v_xsl)).getclobval ();
  v_return := REPLACE (v_return, '&apos;', '''');
  DBMS_OUTPUT.put_line (   'After XMLTYPE.transform with a BIG XML: '
                        || TO_CHAR (SYSDATE, 'hh:mi:ss'));
  DBMS_OUTPUT.put_line (SUBSTR (v_return, 1, 255));
-- Ce résultat est très long à obtenir (3 minutes sur mon serveur) alors qu'il est obtenu
-- très rapidement avec d'autres transformers XSL comme oraxsl et même Internet Explorer sur un PC...
END;