我一直在尝试使用 XSLT 在最有效的时间内从 XML 文档中获取 CSV 数据。以下是我的示例 XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<sObjects xmlns="urn:sobject.partner.soap.sforce.com">
<sObject>
<Name>Raagu</Name>
<BillingStreet>Hoskote</BillingStreet>
</sObject>
<sObject>
<Name>Rajath</Name>
<BillingStreet>BTM</BillingStreet>
<age>25</age>
</sObject>
<sObject>
<Name>Sarath</Name>
<BillingStreet>Murgesh</BillingStreet>
<location>Bangalore</location>
<age>#N/A</age>
</sObject>
<sObject>
<Name>Bharath</Name>
<BillingStreet>EGL</BillingStreet>
<location>Bangalore</location>
<shipping>Hoskote</Shipping>
</sObject>
<sObject>
<Id>12312321321</Id>
<Name>Guru</Name>
<location>Sirsi</location>
<date>12-12-12</date>
</sObject>
<sObject>
<Name>Appa</Name>
<BillingStreet>someStrrt</BillingStreet>
<accountNo>213213</accountNo>
</sObject>
<sObject>
<Name>Sarath</Name>
<BillingStreet>Murgesh</BillingStreet>
<location>Bangalore</location>
</sObject>
<sObject>
<Name>Sarath</Name>
<BillingStreet>Murgesh</BillingStreet>
<location>Bangalore</location>
</sObject>
<sObject>
<Name>Sarath</Name>
<BillingStreet>Murgesh</BillingStreet>
<location>Bangalore</location>
</sObject>
我想要这种输出
<?xml version="1.0" encoding="utf-8"?><csv xmlns="http://www.approuter.com/schemas/RootNode"><data>Name,BillingStreet,age,location,Shipping,Id,date,accountNo
Raagu,Hoskote,,,,,,
Rajath,BTM,25,,,,,
Sarath,Murgesh,#N/A,Bangalore,,,,
Bharath,EGL,,Bangalore,Hoskote,,,
Guru,,,Sirsi,,12312321321,12-12-12,
Appa,someStrrt,,,,,,213213
Sarath,Murgesh,,Bangalore,,,,
Sarath,Murgesh,,Bangalore,,,,
Sarath,Murgesh,,Bangalore,,,,</data></csv>
为了完成这件事,我尝试了遵循 XSLT
<xsl:stylesheet version="1.0" xmlns:p0="urn:sobject.partner.soap.sforce.com" xmlns:csv="csv:csv" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" method="xml"/>
<xsl:strip-space elements="*" />
<xsl:variable name="delimiter" select="','"/>
<xsl:key name="field" match="p0:sObject/*" use="name()"/>
<!-- variable containing the first occurrence of each field -->
<xsl:variable name="allFields"
select="/*/*/*[generate-id()=generate-id(key('field', name())[1])]"/>
<xsl:template match="/">
<!-- Output the CSV header -->
<xsl:element name="csv" namespace="http://www.approuter.com/schemas/RootNode">
<xsl:element name="data" namespace="http://www.approuter.com/schemas/RootNode">
<xsl:for-each select="$allFields">
<xsl:value-of select="name()" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:text>
 </xsl:text>
<xsl:apply-templates select="/*/p0:sObject" />
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="p0:sObject">
<xsl:variable name="this" select="." />
<xsl:for-each select="$allFields">
<xsl:value-of select="$this/*[name() = name(current())]" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:if test="position() < last()">
<xsl:text>
 </xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
从功能性的角度来看,上述 XSLT 工作得非常好。但我正在尝试处理大约 10000 条记录。即 sObject 元素上的 10000 个实例,每个 sObject 将包含大约 15 个字段。
如果我在 XSLT 上运行它来处理这么多的记录,它就会被折腾。XSLT 大约需要 20 分钟来处理和提供 csv 数据。我想在几秒钟内完成这项工作。也就是说,XSLT 应该花费 3-4 秒来处理 10k 条记录(sObject 条目)以提供有效的 CSV 数据,如上所示。
这就是我坚持要增强 XSLT 并且需要帮助来修改此 XSLT 以更快地工作的地方。