XML到CSV缺少字段

时间:2016-08-03 08:13:15

标签: xml csv

我使用this tool从ebay XML文件制作CSV。

我已经在notepad ++中使用正则表达式删除了所有发货目的地,因为它们是不必要的。然后我删除了(<sellingStatus>|</sellingStatus>)因为我认为这棵树太深了(我是一个XML菜鸟)。但是,当转换完成后,价格不会出现在CSV上。

以下XML示例。有人可以解释为什么价格没有被转换器拿起来,理想情况下建议使用正则表达式来修复它吗?

<?xml version='1.0' encoding='UTF-8'?>
<findItemsIneBayStoresResponse xmlns="http://www.ebay.com/marketplace/search/v1/services">
    <ack>Success</ack>
    <version>1.13.0</version>
    <timestamp>2016-08-03T06:19:01.316Z</timestamp>
    <searchResult count="97">
        <item>
            <itemId>152174882749</itemId>
            <title>Yolande' Butterfly Blue #' print of original Watercolour , A4 size.</title>
            <globalId>EBAY-GB</globalId>
            <primaryCategory>
                <categoryId>60437</categoryId>
                <categoryName>Paintings</categoryName>
            </primaryCategory>
            <galleryURL>http://thumbs2.ebaystatic.com/m/m_VMlLhEdNRYkHi-6hUvbLg/140.jpg</galleryURL>
            <viewItemURL>http://www.ebay.co.uk/itm/Yolande-Butterfly-Blue-print-original-Watercolour-A4-size-/152174882749</viewItemURL>
            <paymentMethod>PayPal</paymentMethod>
            <autoPay>false</autoPay>
            <postalCode>TQ110DD</postalCode>
            <location>Buckfastleigh,United Kingdom</location>
            <country>GB</country>
                <currentPrice currencyId="GBP">12.5</currentPrice>
                <convertedCurrentPrice currencyId="GBP">12.5</convertedCurrentPrice>
                <sellingState>Active</sellingState>
                <timeLeft>P16DT11H53M5S</timeLeft>
            <listingInfo>
                <bestOfferEnabled>true</bestOfferEnabled>
                <buyItNowAvailable>false</buyItNowAvailable>
                <startTime>2016-07-20T18:12:06.000Z</startTime>
                <endTime>2016-08-19T18:12:06.000Z</endTime>
                <listingType>StoreInventory</listingType>
                <gift>false</gift>
            </listingInfo>
            <isMultiVariationListing>false</isMultiVariationListing>
            <topRatedListing>false</topRatedListing>
        </item>
        <item>
            <itemId>152181312690</itemId>
            <title>'Peacock' print of original Watercolour by Yolande, A4 size.</title>
            <globalId>EBAY-GB</globalId>
            <primaryCategory>
                <categoryId>60437</categoryId>
                <categoryName>Paintings</categoryName>
            </primaryCategory>
            <galleryURL>http://thumbs3.ebaystatic.com/m/m42A7QDsUeNNpkQylOnmMmg/140.jpg</galleryURL>
            <viewItemURL>http://www.ebay.co.uk/itm/Peacock-print-original-Watercolour-Yolande-A4-size-/152181312690</viewItemURL>
            <paymentMethod>PayPal</paymentMethod>
            <autoPay>false</autoPay>
            <postalCode>TQ110DD</postalCode>
            <location>Buckfastleigh,United Kingdom</location>
            <country>GB</country>
                <currentPrice currencyId="GBP">12.5</currentPrice>
                <convertedCurrentPrice currencyId="GBP">12.5</convertedCurrentPrice>
                <sellingState>Active</sellingState>
                <timeLeft>P21DT16H47M12S</timeLeft>
            <listingInfo>
                <bestOfferEnabled>true</bestOfferEnabled>
                <buyItNowAvailable>false</buyItNowAvailable>
                <startTime>2016-07-25T23:06:13.000Z</startTime>
                <endTime>2016-08-24T23:06:13.000Z</endTime>
                <listingType>StoreInventory</listingType>
                <gift>false</gift>
            </listingInfo>
            <isMultiVariationListing>false</isMultiVariationListing>
            <topRatedListing>false</topRatedListing>
        </item>

2 个答案:

答案 0 :(得分:1)

不,请请 - 请不要使用regex来破坏您的XML。 It's very bad news.。它创造了脆弱的代码,有一天可能会破坏。

还有其他解决方案。 IMO使用脚本语言(如perl)以您特别想要的方式进行转换,这将是最佳的。

让我们了解您的示例输出将是什么(以及一些有效的XML - 您的遗漏了关闭标记),我可以举个例子。

但它会是这样的:

#!/usr/bin/env perl
use strict;
use warnings 'all'; 

use XML::Twig;

my $twig = XML::Twig -> new -> parsefile('your_file.xml'); 

my @columns_xpath = qw ( itemId title postalCode currentPrice listingType ); 

print join( ",", @columns_xpath ), "\n";

foreach my $item ( $twig -> get_xpath('.//item') ) {
    print join ",", (map { $item -> get_xpath(".//$_", 0 ) -> text } @columns_xpath), "\n";
}

它真的那么简单,并为您提供了更多的输出结构灵活性。 (其他语言也可以做同样的事情 - 我只提供perl,因为我喜欢它,这是一个可靠的选择)。

注意 - 我使用xpath进行搜索。在xpath - 类似regex,但专门针对XML - .//表示在此分支下搜索&#34;。

所以.//listingType会找到./listingInfo/listingType - 这只适用于只有一个(因为他0中的get_xpath说&#39;得到仅限第一个实例)。

根据您的数据,这将会起作用。但你可以省略//并做完全合格的&#39;路径。

从上面生成的输出是:(虽然我必须在XML的末尾添加&#39; close&#39;标记)。

itemId,title,postalCode,currentPrice,listingType
152174882749,Yolande' Butterfly Blue #' print of original Watercolour , A4 size.,TQ110DD,12.5,StoreInventory,
152181312690,'Peacock' print of original Watercolour by Yolande, A4 size.,TQ110DD,12.5,StoreInventory,

所以这里有一个简单的&#34;棍子逗号的缺陷&#34;解决问题的方法。对于输出,我们需要做正确的&#39; CSV - 使用另一个简单的可用模块:

#!/usr/bin/env perl
use strict;
use warnings 'all'; 

use XML::Twig;
use Text::CSV; 

my $twig = XML::Twig -> new -> parsefile ( 'input.xml');
open ( my $output, '>', "results.csv" ) or die $!; 

my @columns_xpath = qw ( itemId title postalCode currentPrice listingType ); 
my $csv = Text::CSV -> new ( {sep_char => ',', eol => "\n" }); 

$csv -> print ( $output, \@columns_xpath );

foreach my $item ( $twig -> get_xpath('.//item') ) {
    my @row = map { $item -> get_xpath(".//$_", 0 ) -> text } @columns_xpath;
    $csv -> print ( $output, \@row );
}
close ( $output );

现在我们正确地引用了CSV:

itemId,title,postalCode,currentPrice,listingType
152174882749,"Yolande' Butterfly Blue #' print of original Watercolour , A4 size.",TQ110DD,12.5,StoreInventory
152181312690,"'Peacock' print of original Watercolour by Yolande, A4 size.",TQ110DD,12.5,StoreInventory

但是要回答你原来的问题 - 是否有任何可能性,因为它sellingState不是sellingStatus

答案 1 :(得分:0)

请尝试以下代码使用C#。

&#13;
&#13;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;


namespace ConsoleApplication6
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        const String CSV = @"c:\temp\test.csv";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            StreamWriter writer = new StreamWriter(CSV);

            Boolean firstRow = true;
            List<string> columnsNames = new List<string>();

            foreach(XElement item in doc.Descendants().Where(x => x.Name.LocalName == "item"))
            {
                List<string> columns = new List<string>();
                foreach (XElement element in item.Elements())
                {
                    if (element.Name.LocalName == "listingInfo")
                    {
                        foreach (XElement listing in element.Elements())
                        {
                            columns.Add(((string)listing).Trim());
                            if (firstRow)
                            {
                                columnsNames.Add(listing.Name.LocalName);
                            }
                        }
                    }
                    else
                    {
                        columns.Add(((string)element).Trim());
                        if (firstRow)
                        {
                            columnsNames.Add(element.Name.LocalName);
                        }
                    }
                }
                if (firstRow)
                {
                    writer.WriteLine(string.Join(",", columnsNames.ToArray()));
                    firstRow = false;
                }
                writer.WriteLine(string.Join(",", columns.ToArray()));
            }
            writer.Flush();
            writer.Close();

        }
    }
}
&#13;
&#13;
&#13;