使用类似XSLT的技术将平面文件转换为XML

时间:2008-11-24 18:57:43

标签: c# .net xml xslt flat-file

我正在设计一个以CSV文件形式从多个合作伙伴接收数据的系统。列的数量和顺序可能不同。在大多数情况下,我会想要选择列的子集,可能会重新排序,然后将它们交给解析器。我显然希望能够将传入的数据转换为某种规范格式,以使解析器尽可能简单。

理想情况下,我希望能够使用某种图形工具为每种传入的数据格式生成转换,并将转换存储为数据库或磁盘上的文档。在收到数据后,我会应用正确的转换(更不用说我如何确定正确的转换)来获取规范格式的XML文档。如果传入的文件包含XML,我就会为每种格式创建一个XSLT文档并且一直在我的路上。

我过去曾经使用过BizTalk的平面文件XSLT扩展(或者其他任何类似的东西),但我不希望在这个项目中出现BizTalk的烦恼(我也买不起)。

有没有人知道是否有替代技术和/或XSLT扩展可以让我以优雅的方式实现我的目标?

我正在使用.NET 3.5 SP1上的C#开发我的应用程序(因此更喜欢.NET支持的技术)。

8 个答案:

答案 0 :(得分:1)

XSLT提供了一些新功能,可以更轻松地解析非XML文件。

Andrew Welch发布了XSLT 2.0 example that converts CSV into XML

答案 1 :(得分:0)

我认为你需要这样的东西(抱歉,.NET不支持,但代码非常简单)

http://csv2xml.sourceforge.net

答案 2 :(得分:0)

IIRC有人创建了一个“LINQ to CSV”库,它可能是创建中间XML(在内存中)作为转换输入的起点。

找到它here

答案 3 :(得分:0)

我在寻找类似的问题空间时找到了两种可能的解决方案。

Progress Software有一套工具和API(.Net),当与.conv(平面到XML转换器)一起使用时,在其Stylus Studio工具中创建的文件允许将任何预定义的平面文件格式转换为运行时的XML。更多信息:http://www.datadirect.com/developer/data-integration/tutorials/converter-sample-code/index.ssp

此外还有一种名为XFLAT的XML格式,它允许以各种格式描述平面文件,分隔,固定宽度等...有一个java程序可以转换平面文件,你已经提供了将XFLAT描述转换为XML,以便您可以继续进行标准的XML到XML XSLT转换。更多细节可以在这里找到:http://www.unidex.com/overview.htm

我从未真正使用过这些工具,但在研究类似问题时发现它们。

答案 4 :(得分:0)

您可以尝试使用LINQ to CSV。微软Eric WhiteMatt Perdeck提供了另一种产品。其他人都在那里......

答案 5 :(得分:0)

检查this article实现处理非XML输入的XmlReader。这不是一个非常困难的任务,一旦你使用它就不需要使用类似XSLT的技术,你可以使用XSLT。

答案 6 :(得分:0)

这将解析linux ip route list命令的输出。这正是我所处理的。

你必须将comman的输出包装在一个名为'output'的元素中,样式表将从那里获取它。这里的真正关键是xpath 2.0规范中的tokenize命令。在此之前我不知道你怎么能这样做。这也不是一个单一的根元素,因为那不是我所需要的。在你的情况下,而不是分裂空间,Id spli on','

<?xml version="1.0" encoding="UTF-8"?>

<xsl:output method="xml" indent="yes" />

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

<xsl:template match="//output">
    <!-- split things up for each new line -->
    <xsl:variable name="line" select="tokenize(.,'\n')"/>
    <xsl:for-each select="$line">                        
        <!-- split each line into peices based on space -->
        <xsl:variable name="split" select="tokenize(.,' +')"/>
        <xsl:if test="count($split) &gt; 1">
            <xsl:element name="route">                                        
                <xsl:for-each select="$split">
                    <xsl:choose>
                        <xsl:when test="position() = 1">
                            <xsl:attribute name="address" select="."/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:variable name="index" select="position()"/>
                            <xsl:variable name="fieldName" select="."/>
                            <xsl:if test="$fieldName and position() mod 2 = 0">
                                <xsl:attribute name="{$fieldName}" select="$split[$index + 1]"/>
                            </xsl:if>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each>
            </xsl:element>
        </xsl:if>
    </xsl:for-each>
</xsl:template>

答案 7 :(得分:-1)

您还可以查看altova's MapForce