关于一周的年龄I asked the question here并得到了很大的帮助。现在我的问题有了延续。最初我不得不将XML转换为文本文件。这是一个示例XML文件:
<DOC xsi:noNamespaceSchemaLocation="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DOC_REQUISITES DOC_DATE="2009-04-23" DOC_NO="99999999"/>
<DOCID TradeDate="2009-04-23" Weekday="Monday" MainFirmId="ZXC0000" FirmName="Firm Name" FirmINN="1234567899">
<FIRM FirmID="FirmId">
<CURRENCY CurrencyId="USD">
<DEPARTMENT DepartmentId="ABCD" DepName="Department Name1">
<SETTLEDATE SettleDate="2009-04-23">
<SECURITY SecurityId="QAZ" SecShortName="SecName1" SecurityType="dc" FaceValue="5">
<TRDACC TrdAccId="ABC00000">
<RECORDS RecNo="1" TradeNo="111" TradeTime="15:15:16" Price="10" Quantity="50" Value="500"/>
</TRDACC>
<TRDACC TrdAccId="SDC00000">
<RECORDS RecNo="2" TradeNo="112" TradeTime="15:15:16" Price="10" Quantity="50" Value="500"/>
<RECORDS RecNo="3" TradeNo="113" TradeTime="15:15:16" Price="20" Quantity="10" Value="200"/>
</TRDACC>
</SECURITY>
<SECURITY SecurityId="WSX" SecShortName="SecName2" SecurityType="dc" FaceValue="1">
<TRDACC TrdAccId="ABC00000">
<RECORDS RecNo="4" TradeNo="114" TradeTime="15:15:13" Price="2" Quantity="1" Value="2"/>
</TRDACC>
</SECURITY>
</SETTLEDATE>
</DEPARTMENT>
<DEPARTMENT DepartmentId="CBSD" DepName="Department Name2">
<SETTLEDATE SettleDate="2009-05-20">
<SECURITY SecurityId="RFV" SecShortName="SecName3" SecurityType="dc" FaceValue="2">
<TRDACC TrdAccId="SDC00000">
<RECORDS RecNo="5" TradeNo="115" TradeTime="15:15:13" Price="100" Quantity="10" Value="1000"/>
</TRDACC>
</SECURITY>
</SETTLEDATE>
</DEPARTMENT>
</CURRENCY>
</FIRM>
</DOCID>
我想要的输出如下:
2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,2009-04-23,QAZ,SecName1,dc,5,ABC00000,1,111,15:15:16,10,50,500
2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,2009-04-23,QAZ,SecName1,dc,5,SDC00000,2,112,15:15:16,10,50,500
2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,2009-04-23,QAZ,SecName1,dc,5,SDC00000,3,113,15:15:16,20,10,200
2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,2009-04-23,WSX,SecName2,dc,1,ABC00000,4,114,15:15:13,2,1,2
2009-04-23,99999999,2009-04-23,Monday,ZXC0000,Firm Name,1234567899,FirmId,USD,CBSD,Department Name2,2009-05-20,RFV,SecName3,dc,2,SDC00000,5,115,15:15:13,100,10,1000
此XSLT已发布给我,它的效果非常好。我真的很感激。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="/DOC/DOCID/FIRM/CURRENCY/DEPARTMENT/SETTLEDATE/SECURITY/TRDACC"/>
</xsl:template>
<xsl:template match="TRDACC">
<!--Select all of the attribute values from the preceding DOC_REQUISITES attibutes, TRDACC ancestor elements, the current element, and all of it's descendants and then apply-templates to those attributes -->
<xsl:apply-templates select="preceding::DOC_REQUISITES/@* | ancestor::*[not(local-name()='DOC')]/@* | @* | descendant::*/@*"/>
<!--Adds a carriage return at the end of the line -->
<xsl:value-of select="' '"/>
</xsl:template>
<!--Template match for attributes that emits the attribute value and a ',', except for the last one -->
<xsl:template match="@*[.!='']">
<xsl:value-of select="."/>
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:template>
</xsl:stylesheet>
这是我的问题: 稍后生成的输出文件将加载到数据库中。表的列对应于xml文件属性。有些列允许Null。这意味着可以省略一些属性。例如,如果attr。 DOC_NO,Weekday,SettleDate,RecNo不存在输出记录必须如下所示:
2009-04-23,,2009-04-23,,ZXC0000,Firm Name,1234567899,FirmId,USD,ABCD,Department Name1,,QAZ,SecName1,dc,5,ABC00000,,111,15:15:16,10,50,500
换句话说,我需要检查每个属性的存在。我尝试解决它,但我的xslt知识非常有限。请帮我。谢谢。
答案 0 :(得分:1)
以前版本的样式表依赖于XML文档的结构来驱动大量输出,通常称为“推送”方法。
如果您不确定自己是否拥有某些属性,则可以使用更像“拉”的样式表,并特别按特定顺序询问某些属性:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="/DOC/DOCID/FIRM/CURRENCY/DEPARTMENT/SETTLEDATE/SECURITY/TRDACC"/>
</xsl:template>
<xsl:template match="TRDACC">
<xsl:value-of select="preceding::DOC_REQUISITES/@DOC_DATE"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="preceding::DOC_REQUISITES/@DOC_NO"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::DOCID/@TradeDate"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::DOCID/@Weekday"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::DOCID/@MainFirmId"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::DOCID/@FirmName"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::DOCID/@FirmINN"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::FIRM/@FirmID"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::CURRENCY/@CurrencyId"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::DEPARTMENT/@DepartmentId"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::DEPARTMENT/@DepName"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::SETTLEDATE/@SettleDate"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::SECURITY/@SecurityId"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::SECURITY/@SecShortName"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::SECURITY/@SecurityType"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="ancestor::SECURITY/@FaceValue"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="@TrdAccId"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="RECORDS/@RecNo"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="RECORDS/@TradeNo"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="RECORDS/@TradeTime"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="RECORDS/@Price"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="RECORDS/@Quantity"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="RECORDS/@Value"/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
如果该属性不存在,则不为该值选择任何内容,并在逗号之间留下空白位置。
答案 1 :(得分:0)
如果没有详细的分析,我认为您所要做的就是更改最后一个模板并删除非空测试[.!='']
,使其看起来像这样
<xsl:template match="@*">
答案 2 :(得分:0)
我认为我必须为每个可能的属性做类似的事情:
<xsl:choose>
<xsl:when test="@Weekday">
<xsl:value-of select="@Weekday"/>
<xsl:text>,</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>,</xsl:text>
</xsl:otherwise>
</xsl:choose>
因此,如果它存在,它将把值放在记录中,如果不仅仅是“,”。但我不知道如何将其嵌入到我已经拥有的XSLT中。
如果任何属性=“”,您建议工作的内容 ,但我需要检查属性是否存在,因为有一个与表列匹配的可能属性列表,XML输入文件可能没有全部。 - klipa 3小时前[删除评论]
答案 3 :(得分:0)
由于输出将加载到数据库中,因此输出中列的排序很重要。
由于空节点集的字符串值是空字符串,因此不存在任何属性存在的测试。
我在DOCID和SECURITY中以不同的方式生成输出,使用看起来更干净的样式。
我还添加了xsl:strip-space来忽略输入文档中的空格。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />
<xsl:strip-space elements="*" />
<xsl:template match="RECORDS">
<xsl:apply-templates select="ancestor::DOCID" mode="print" />
<xsl:apply-templates select="ancestor::FIRM" mode="print" />
<xsl:apply-templates select="ancestor::FIRM/CURRENCY" mode="print" />
<xsl:apply-templates select="ancestor::DEPARTMENT" mode="print" />
<xsl:apply-templates select="ancestor::SETTLEDATE" mode="print" />
<xsl:apply-templates select="ancestor::SECURITY" mode="print" />
<xsl:apply-templates select="ancestor::TRDACC" mode="print" />
<xsl:value-of select="@RecNo" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@TradeNo" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@TradeTime" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@Price" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@Quantity" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@Value" />
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template match="DOCID" mode="print">
<xsl:value-of select="@TradeDate" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@Weekday" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@WMainFirmId" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@FirmName" />
<xsl:text>,</xsl:text>
<xsl:value-of select="@WFirmINN" />
<xsl:text>,</xsl:text>
</xsl:template>
<xsl:template match="SECURITY" mode="print">
<xsl:value-of select="concat(@SecurityId,',',@SecShortName,',',@SecurityType,',',@FaceValue,',')" />
</xsl:template>
<!-- etc for each element we apply in the RECORD template -->
</xsl:stylesheet>