2009-03-09 10 views
1

Wir müssen eine XML-Datei mit XSLT in eine CVS-Datei analysieren. Der folgende Code funktioniert aber nur wenn die Felder in der XML immer konstant sind.Wie kann diese XSLT um dynamische XML-Felder erweitert werden?

Die Felder in unserer XML-Datei variieren immer. Wie kann ich meine XSLT-Datei so ändern, dass sie alle Felder aus der XML-Datei dynamisch in die CSV-Datei einfügt?

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> 

Hier ist die ASP.NET-Datei, die die Dateien, die oben analysiert:

<%@ 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

Verwenden Sie XslCompiledTransform anstelle von XslTransform – Tawani

Antwort

3

Ich erinnerte mich an etwas ähnlichem eines Arbeits Weg zurück, und auf der Suche durch mein Archiv zu tun, lo-und-siehe:

<?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> 

All die hässlichen, aber funktional Hagel.

Ich bin ernsthaft nicht stolz darauf, aber ich habe für Ihre Daten aktualisiert und getestet und es funktioniert.

+0

direkt auf, das ist es, 1000 danke! –

1

nic anderen for-each Schleife die Arbeit für Sie erledigen?

<?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> 

Grüße,

Aaron

+0

Ja, ich muss schließlich alle Felder aus jeder Zeile enthalten, aber was in dieser Aufgabe schwierig ist, ist (1) die Titelzeile muss eine DISTINCT-Liste aller Feldnamen aus allen enthalten Zeilen, und (2) jede Zeile muss die entsprechenden "leeren" Felder liefern, die nicht in dieser Zeile vorkommen, aber in anderen tun –

0

Das Problem hierbei ist, dass die erste "Reihe" 3 Elemente und andere Reihen 5 Elemente enthalten könnte. Es wird also schwierig sein, den Header zu extrahieren.

Zur Verwendung xsl:sort

zählen verwenden die XSLT-Funktion count()

Sortieren nach der Anzahl der Elemente, erhalten die Header, erstellen Sie eine Sammlung von Gegenständen in der Kopfzeile sortieren dann für jede Zeile, es scannen für diese Elemente.

Verwandte Themen