CSV en XML en utilisant xslt - comment avoir incrémentation nom de la colonne
J'ai cette xslt pour convertir un fichier csv en xml, fonctionne très bien, sauf que la balise est la même pour toutes les colonnes.
J'en ai besoin pour incrémenter comme ce
<row>
<column1></column1>
<column2></column2>
<column3></column3>
</row>
lorsque j'utilise la position() il renomme toutes les colonnes à colonne1
<xsl:element name="{concat('column', position())}">
Ici est le xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:variable name="LF" select="'
'"/>
<!-- template that matches the root node-->
<xsl:template match="/">
<root>
<xsl:call-template name="texttorows">
<xsl:with-param name="StringToTransform" select="/root"/>
</xsl:call-template>
</root>
</xsl:template>
<!-- template that actually does the conversion-->
<xsl:template name="texttorows">
<!-- import $StringToTransform-->
<xsl:param name="StringToTransform" select="''"/>
<xsl:choose>
<!-- string contains linefeed-->
<xsl:when test="contains($StringToTransform,$LF)">
<!-- Get everything up to the first carriage return-->
<row>
<xsl:call-template name="csvtoxml">
<xsl:with-param name="StringToTransform" select="substring-before($StringToTransform,$LF)"/>
</xsl:call-template>
</row>
<!-- repeat for the remainder of the original string-->
<xsl:call-template name="texttorows">
<xsl:with-param name="StringToTransform">
<xsl:value-of select="substring-after($StringToTransform,$LF)"/>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<!-- string does not contain newline, so just output it-->
<xsl:otherwise>
<row>
<xsl:call-template name="csvtoxml">
<xsl:with-param name="StringToTransform" select="$StringToTransform"/>
</xsl:call-template>
</row>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="csvtoxml">
<!-- import $StringToTransform-->
<xsl:param name="StringToTransform" select="''"/>
<xsl:choose>
<!-- string contains linefeed-->
<xsl:when test="contains($StringToTransform,',')">
<!-- Get everything up to the first carriage return-->
<xsl:element name="{concat('column', position())}">
<xsl:value-of select="substring-before($StringToTransform,',')"/>
</xsl:element>
<!-- repeat for the remainder of the original string-->
<xsl:call-template name="csvtoxml">
<xsl:with-param name="StringToTransform">
<xsl:value-of select="substring-after($StringToTransform,',')"/>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<!-- string does not contain newline, so just output it-->
<xsl:otherwise>
<column>
<xsl:value-of select="$StringToTransform"/>
</column>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Voici un exemple de fichier csv.
<root>
3779490,916705,CS,60,34.89,Sauce/Cholula
5918104,918958,CS,6,20.63,Pasta/Fresh/Cavatelli/6#/Frozen
5064774,920723,CS,10,45.5,Cheese/Oaxaca
3422752,925230,EA,8,69.6,Chipotle/Powder/Ground
5955640,BB171,CS,30,50.7,Butter/Unsalted
5295326,BC110005,CS,6000,54.95,Oil/Olive/Finishing
</root>
+1: un bien exprimée question. Cependant: essayer de lire un code pour faire défiler horizontalement et verticalement, c'est difficile. Suggérer de réduire le retrait et la rupture des lignes plus tôt (vérifiez l'aperçu). Ne cherche pas à être difficile, mais pour vous aider à obtenir de l'aide.
Concernant votre question principale,
Je suis d'accord. Je devrais avoir utilisé un petit tiret. J'ai juste copié à partir de visual studio.
On dirait que vous êtes à l'aide de XSLT 1.0 . Il est utile de marquer votre XSLT questions avec la de XSLT 1.0 tag ou le XSLT 2.0 tag. Bien que cela ne répond pas à votre question, cette bibliothèque de feuille de style peut être utile pour vous, si vous décidez de mettre à niveau pour XSLT 2.0: pascaliburnus.seanbdurkin.id.ua/index.php?/archives/... .
Concernant votre question principale,
position()
ne retourne pas à la position de l'élément de sortie dans son parent. Plutôt elle retourne la position du nœud de contexte dans le contexte de la séquence (qui dépend du contexte, naturellement). Généralement c'est la position du nœud de contexte parmi ses frères et sœurs dans le document d'entrée (voir la section w3.org/TR/xpath/#function-position)Je suis d'accord. Je devrais avoir utilisé un petit tiret. J'ai juste copié à partir de visual studio.
On dirait que vous êtes à l'aide de XSLT 1.0 . Il est utile de marquer votre XSLT questions avec la de XSLT 1.0 tag ou le XSLT 2.0 tag. Bien que cela ne répond pas à votre question, cette bibliothèque de feuille de style peut être utile pour vous, si vous décidez de mettre à niveau pour XSLT 2.0: pascaliburnus.seanbdurkin.id.ua/index.php?/archives/... .
OriginalL'auteur gangt | 2012-08-17
Vous devez vous connecter pour publier un commentaire.
Il semble qu'
csvtoxml
est appelée une chaîne de grande taille et il fonctionne de manière récursive un chemin à travers cette chaîne.position()
ne fonctionne pas dans ce cas, parce que vous ne travaillez pas avec un ensemble de nœuds.Au lieu de cela, vous pourriez être en mesure de réaliser ce que vous êtes après, avec un comptage de param:
Vous aurez besoin de concat le numéro de la colonne dans votre
xsl:otherwise
.Qui a fait le tour.
Bonne réponse, mais, s'il vous plaît, évitez d'utiliser
xsl:value-of
dans le corps d'unxsl:param
(ou dans le corps d'unxsl:variable
). Cette inutilement crée un arbre, un enfant du nœud de texte-créer des ce et de l'obtention de sa chaîne de valeur, plus tard, est plutôt inefficace. Dans tous ces cas, il suffit de déplacer leselect
attribut jusqu'à laxsl:param
et de définir l'avoir corps est vide.Bon à savoir, merci!
OriginalL'auteur Derek Hunziker
Bien que XSLT est capable de traiter les non-XML de contenu, il ne semble pas être conçu comme un outil de transformation de texte. En conséquence, la plupart des outils disponibles pour vous sur la manipulation du XML infoset des constructions comme les éléments et les attributs. Il y a un peu de soutien pour les chaînes de texte, mais pas beaucoup. Donc
position()
est définie en termes de nœuds d'entrée.http://www.w3.org/TR/xpath/#section-Node-Set-Functions:
http://www.w3.org/TR/xslt#section-Expressions:
Depuis votre entrée est juste une chaîne de texte, vous êtes toujours en position 1. Je peux penser qu'à une seule façon de le faire avec XSLT. Transformer deux fois. La première transformer vous donne la structure de base de l'onu-numéroté éléments de colonne. La deuxième transformer les numéros de la colonne éléments. Parce que vous êtes la sélection des nœuds d'un document XML la deuxième fois,
position()
doit avoir les valeurs que vous voulez.OriginalL'auteur John Watts
Bien que l'OP est probablement à la recherche d'une transformation XSLT 1.0 solution, pour que l'intérêt ici est d'une transformation XSLT 2.0 solution. Cette solution nécessite de télécharger mon csv-xml bibliothèque de feuille de style à partir d'ici, ce qui est discuté dans cette entrée de blog.
Avec ce que le document d'entrée, mentionnés dans la feuille de style avec l'uri 'gangt.csv' (utilisation d'un paramètre ou d'adapter comme vous le désirez)...
gangt.csv
Feuille de Style
...ce XSLT 2.0 feuille de style...
Sortie
...produit le présent document de sortie...
J'ai mis à jour le blog en lien. Il n'existe pas de restrictions de droit d'auteur. Sentez-vous libre d'utiliser comme vous le souhaitez.
OriginalL'auteur Sean B. Durkin
Je ne suis pas sûr de savoir pourquoi vous êtes en optant pour XSLT dans ce cas. Ce n'est pas le premier choix pour le traitement des chaînes de telles opérations, en particulier depuis votre source de données n'est pas du XML, vous êtes juste en l'enveloppant dans un nœud pour le rendre XML. Un plus évident approche serait de gérer le CSV via quelque chose comme PHP.
En tout cas, pour répondre à la question, si vous avez accès à EXSLT (ce qui est souvent disponible avec les processeurs XSLT, par exemple PHP):
Runnable démo ici (voir la sortie source).
S'il est vrai XSLT 1.0 n'est pas très efficace pour csv vers xml conversion, je pense qu'il n'est pas correct de les généraliser à d'autres versions de XSLT. XSLT 2.0 est effectivement très efficace, et XSLT 3.0 a même une fonction native pour elle.
str:split n'est pas une solution robuste. Le problème est que sur les lignes, il ne gère pas la variété de la ligne des terminaisons possibles (CR.LF rapport LF par exemple), et sur les valeurs qu'il ne gère pas les valeurs à la cote et double échappement " les marques qui sont communs dans le format csv.
OriginalL'auteur Utkanos