[XSLT]XML vers XML avec des transformations de texte au passage
Bonjour,
Je me retrouve avec le fichier XML suivant dont je dois modifier le contenu texte de certains noeuds (nettoyer le T et Z de la date UTC, rempalcer les acronymes par des mots complets etc) :
Code:
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 187 188 189 190 191 192 193
| <?xml version="1.0" encoding="UTF-8"?>
<SyncMaterialDefinition>
<ApplicationArea>
<CreationDateTime>2007-09-18T18:30:00.0Z</CreationDateTime>
</ApplicationArea>
<DataArea>
<Sync/>
<MaterialDefinition>
<ID>0311000</ID>
<Description>Citropepsin plyn</Description>
<MaterialDefinitionProperty>
<ID>MaterialType</ID>
<Value>
<ValueString>SFP</ValueString>
<DataType>ID</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>BaseUnitOfMeasure</ID>
<Value>
<ValueString>KG</ValueString>
<DataType>NOTATION</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>BatchManagement</ID>
<Value>
<ValueString>1</ValueString>
<DataType>boolean</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>TotalShelfLive</ID>
<Value>
<ValueString>60</ValueString>
<DataType>integer</DataType>
<UnitOfMeasure>Days</UnitOfMeasure>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>TimeStamp</ID>
<Value>
<ValueString>2004-08-21T14:00:00.0Z</ValueString>
<DataType>dateTime</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
</MaterialDefinition>
<MaterialDefinition>
<ID>1341750001</ID>
<Description>Pepsyna</Description>
<MaterialDefinitionProperty>
<ID>MaterialType</ID>
<Value>
<ValueString>RM</ValueString>
<DataType>ID</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>BaseUnitOfMeasure</ID>
<Value>
<ValueString>KG</ValueString>
<DataType>NOTATION</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>BatchManagement</ID>
<Value>
<ValueString>1</ValueString>
<DataType>boolean</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>TotalShelfLive</ID>
<Value>
<ValueString>200</ValueString>
<DataType>integer</DataType>
<UnitOfMeasure>Days</UnitOfMeasure>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>TimeStamp</ID>
<Value>
<ValueString>2003-12-03T12:37:57.0Z</ValueString>
<DataType>dateTime</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
</MaterialDefinition>
<MaterialDefinition>
<ID>1331420004</ID>
<Description>Kwas cytrynowy</Description>
<MaterialDefinitionProperty>
<ID>MaterialType</ID>
<Value>
<ValueString>RM</ValueString>
<DataType>ID</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>BaseUnitOfMeasure</ID>
<Value>
<ValueString>G</ValueString>
<DataType>NOTATION</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>KgPerUnit</ID>
<Value>
<ValueString>0.001</ValueString>
<DataType>decimal</DataType>
<UnitOfMeasure>KG</UnitOfMeasure>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>BatchManagement</ID>
<Value>
<ValueString>1</ValueString>
<DataType>boolean</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>TotalShelfLive</ID>
<Value>
<ValueString>150</ValueString>
<DataType>integer</DataType>
<UnitOfMeasure>Days</UnitOfMeasure>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>TimeStamp</ID>
<Value>
<ValueString>2001-02-12T08:25:56.0Z</ValueString>
<DataType>dateTime</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
</MaterialDefinition>
<MaterialDefinition>
<ID>1331730001</ID>
<Description>Fosforan 1-zasad. sodowy x2H2O</Description>
<MaterialDefinitionProperty>
<ID>MaterialType</ID>
<Value>
<ValueString>RM</ValueString>
<DataType>ID</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>BaseUnitOfMeasure</ID>
<Value>
<ValueString>KG</ValueString>
<DataType>NOTATION</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>BatchManagement</ID>
<Value>
<ValueString>1</ValueString>
<DataType>boolean</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>TotalShelfLive</ID>
<Value>
<ValueString>200</ValueString>
<DataType>integer</DataType>
<UnitOfMeasure>Days</UnitOfMeasure>
</Value>
</MaterialDefinitionProperty>
<MaterialDefinitionProperty>
<ID>TimeStamp</ID>
<Value>
<ValueString>2001-02-12T08:25:56.0Z</ValueString>
<DataType>dateTime</DataType>
<UnitOfMeasure/>
</Value>
</MaterialDefinitionProperty>
</MaterialDefinition>
</DataArea>
</SyncMaterialDefinition> |
J'ai effectué la modification des textes en créant les templates XSLT suivants :
Code:
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
|
<!-- BEGIN Templates -->
<xsl:template match="/">
<xsl:apply-templates select="//UnitOfMeasure"/>
</xsl:template>
<xsl:template match="/SyncMaterialDefinition" >
<xsl:for-each select="DataArea/MaterialDefinition/MaterialDefinitionProperty">
<xsl:if test="ID = 'TimeStamp' ">
<xsl:value-of select="concat(substring(Value/ValueString,1,10), ' ', substring(Value/ValueString,12,8) )" />
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="/SyncMaterialDefinition/ApplicationArea">
<xsl:value-of select="concat(substring(CreationDateTime,1,10), ' ', substring(CreationDateTime,12,8) )"/>
</xsl:template>
<xsl:template match="/SyncMaterialDefinition/DataArea/MaterialDefinition">
<xsl:for-each select="MaterialDefinitionProperty">
<xsl:if test="ID = 'MaterialType' ">
<xsl:choose>
<xsl:when test=" Value/ValueString = 'RM' " >
<xsl:value-of select=" 'Raw material' " />
</xsl:when>
<xsl:when test=" Value/ValueString = 'PI' ">
<xsl:value-of select=" 'Packaging articles' " />
</xsl:when>
<xsl:when test=" Value/ValueString = 'SFP' ">
<xsl:value-of select=" 'Semi Finished Product' " />
</xsl:when>
<xsl:when test=" Value/ValueString = 'FP' ">
<xsl:value-of select=" 'Finished Product' " />
</xsl:when>
<xsl:when test=" Value/ValueString = 'CONT' ">
<xsl:value-of select=" 'Container' " />
</xsl:when>
</xsl:choose>
</xsl:if>
<!-- Converts units of mesure -->
<xsl:if test="ID = 'BaseUnitOfMeasure' ">
<xsl:choose>
<xsl:when test="Value/ValueString = 'G' ">
<xsl:value-of select="Grams" />
</xsl:when>
<xsl:when test="Value/ValueString = 'KG' ">
<xsl:value-of select=" 'Kilograms' " />
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- END Templates --> |
J'ai bien trouvé comment reproduire tout un XML en appelant ce template depuis le noeud racine :
Code:
1 2 3 4 5 6
|
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template> |
Mais ce qui me pose problème, c'est de recracher un XML reproduisant le document XML de départ, AVEC les champs textes transformés par les templates ci-dessus.
Transformer les textes via XSLT est fait. Reproduire l'intégralité du texte XML source est ok. Mais faire les deux à la fois : aïe aïe aïe. Je me retrouve souvent avec des <xsl:for-each> imbriqués aboutissant à ... des stack overflow, sans doute causés par des boucles infinies.
En résumé, (je crois que) j'ai un problème d'application de mes templates.
Merci d'avance :)
PS : J'ai appris XSLT sur le tas et ai cherché une équivalence avec des choses que je connaissais d'autres langages (quand j'avais besoin d'un "switch case", j'ai cherché un équivalent XSLT et suis tombé "xsl:choose" par exemple), donc je n'ai sûrement pas une façon de faire orthodoxe en XSLT et prie les puristes du XSLT et XPath de pardonner l'utilisation étrange que j'ai dû faire de ces langages. Idem avec le recours a substring() et concat() pour reformater mes dates ...