2009-03-09 5 views
1

Nous devons analyser un fichier XML avec XSLT dans un fichier CVS. Le code ci-dessous fonctionne mais seulement si les champs dans le XML sont toujours constants.Comment étendre ce XSLT pour inclure dynamiquement des champs XML?

Les champs du fichier XML vont toujours varier. Comment puis-je modifier mon fichier XSLT afin qu'il inclue dynamiquement dans le fichier CSV tous les champs du fichier XML?

XML:

<?xml version="1.0" encoding="iso-8859-1"?> 
<data> 
    <row> 
     <customerID>06104539-463E-4B1A-231-34342343434</customerID> 
     <contactID>23434-99F2-4325-B228-6F343483469389FB</contactID> 
     <firstName>Jim</firstName> 
     <lastName>Smith</lastName> 
    </row> 
    <row> 
     <customerID>223434-463E-4B1A-231-A1E7EA248796</customerID> 
     <contactID>6675767-99F2-4325-B234328-6F83469389FB</contactID> 
     <specialID>112332</specialID> 
     <firstName>John</firstName> 
     <middleName>S.</middleName> 
     <lastName>Jones</lastName> 
    </row> 
</data> 

XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?> 

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="/"> 
    customerID,contactID<br/> 
    <xsl:for-each select="data/row"> 
     <xsl:value-of select="customerID"/>,<xsl:value-of select="contactID"/><br/> 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 

Voici le fichier ASP.NET qui analyse les fichiers ci-dessus:

<%@ Page Language="c#" %> 
<%@ import Namespace="System.Xml" %> 
<%@ import Namespace="System.Xml.Xsl" %> 
<%@ import Namespace="System.Xml.XPath" %> 
<%@ import Namespace="System.IO" %> 
<%@ import Namespace="System.Text" %> 
<script runat="server"> 

    public void Page_Load(Object sender, EventArgs E) { 

     string xmlPath = Server.MapPath("test2.xml"); 
     string xslPath = Server.MapPath("test2.xsl"); 

     StreamReader reader = null;; 
     XmlTextReader xmlReader = null; 

     FileStream fs = new FileStream(xmlPath, FileMode.Open, FileAccess.Read); 
     reader = new StreamReader(fs,Encoding.UTF7); 
     xmlReader = new XmlTextReader(reader); 
     XPathDocument doc = new XPathDocument(xmlReader); 

     XslTransform xslDoc = new XslTransform(); 
     xslDoc.Load(xslPath); 

     xslDoc.Transform(doc,null, Response.Output); 

     reader.Close(); 
     xmlReader.Close(); 

    } 

</script> 
+0

Utiliser XslCompiledTransform au lieu de XslTransform – Tawani

Répondre

3

Je me suis souvenu de faire quelque chose de similaire une façons dos, et en regardant à travers mon travail d'archives, lo-et-voici:

<?xml version="1.0" encoding="ISO-8859-1"?> 

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:key name="muench" match="/data/row/*" use="local-name()"/> 

    <xsl:template match="/"> 
     <xsl:for-each select="/data/row/*[generate-id() = generate-id(key('muench',local-name())[1])]"> 
      <xsl:if test="not(position()=1)">,</xsl:if><xsl:value-of select="local-name()"/> 
     </xsl:for-each> 
     <br/> 
     <xsl:for-each select="/data/row"> 
      <xsl:variable name="current" select="."/> 
      <xsl:for-each select="/data/row/*[generate-id() = generate-id(key('muench',local-name())[1])]"> 
       <xsl:variable name="field" select="local-name()"/> 
       <xsl:if test="not(position()=1)">,</xsl:if><xsl:value-of select="$current/*[local-name()=$field]"/>    
      </xsl:for-each> 
      <br/> 
     </xsl:for-each> 
    </xsl:template> 

</xsl:stylesheet> 

Toute la grêle le laid, mais fonctionnelle. Je ne suis pas vraiment fier de cela, mais j'ai mis à jour pour vos données et testé et cela fonctionne.

+0

droite, c'est tout, 1000 merci! –

1

Est-ce pas une autre pour chaque- boucle faire le travail pour vous?

<?xml version="1.0" encoding="ISO-8859-1"?> 
    <xsl:stylesheet version="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     customerID,contactID<br/> 
     <xsl:for-each select="data/row"> 
     <xsl:for-each select="*"> 
      <xsl:value-of select="."/>, 
     </xsl:for-each> 
     <br/>  
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

Cordialement,

Aaron

+0

Oui, j'ai finalement besoin d'inclure tous les champs de chaque ligne, mais ce qui est compliqué dans cette tâche est (1) la ligne de titre doit inclure une liste DISTINCT de tous les noms de champs lignes, et (2) chaque ligne doit fournir les champs "vides" appropriés qui ne se produisent pas dans cette ligne, mais faire dans d'autres –

0

Le problème ici est que la première "ligne" pourrait contenir 3 éléments et autres lignes 5 éléments. Il sera donc difficile d'extraire l'en-tête.

Pour SORT xsl:sort

Pour compter utiliser la fonction xslt count()

Trie après le nombre d'éléments, obtenir l'en-tête, créer une collection d'éléments dans l'en-tête puis, pour chaque ligne, le scanner pour ces éléments.

Questions connexes