如何扩展此XSLT以动态包含XML字段?

时间:2009-03-09 14:11:55

标签: xml xslt

我们需要使用XSLT将XML文件解析为CVS文件。下面的代码工作但仅当 XML中的字段始终是常量时。

我们的XML文件中的字段总是会有所不同。 如何更改我的XSLT文件,以便在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>

以下是解析上述文件的ASP.NET文件:

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

3 个答案:

答案 0 :(得分:3)

我记得做过类似的事情,回顾我的档案工作,瞧不起:

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

所有人都欢呼丑陋但功能齐全。

我真的不为此感到自豪,但我已经更新了您的数据并对其进行了测试并且确实有效。

答案 1 :(得分:1)

另一个for-each循环不会为你做这个工作吗?

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

此致

亚伦

答案 2 :(得分:0)

这里的问题是第一个“行”可以包含3个元素和其他行5个元素。因此提取标题将很困难。

要排序使用xsl:sort

要计算使用xslt函数count()

在元素数量之后排序,获取标题,然后在标题中创建项目集合,然后为每一行扫描这些元素。