[英]Convert XML file to CSV
在使用正則表達式轉換了混亂的XML之后,我現在需要再次更改它。 這個源文件
<product>
<sku>SP00001</sku>
<PID_OWNER_SellerID>StoreName</PID_OWNER_SellerID>
<EANCode>8711983489813</EANCode>
<DeliveryDays>2</DeliveryDays>
</product>
必須成為CSV文件,但是像這樣:
sku field value
SP00001 PID_OWNER_SellerID StoreName
SP00001 EANCode 8711983489813
SP00001 DeliveryDays 2
我認為這超出了regex的范圍,必須使用XSL完成嗎?
嘗試使用正則表達式解析XML通常是一個壞主意,因為存在一種無限的方式來格式化結構上相同的XML文檔,但是會簡化您的正則表達式。
對於體積不大的文件,一定要使用XSL,記住要指定“文本”作為輸出方法。 不要忘記,如果需要,您可以通過編程方式調用XSL流程-大多數語言都允許您這樣做。
對於大文件,請考慮編寫一個使用流API(例如SAX或推送分析器API之一)的小程序。
這是一些適合您的XSLT ...
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl"
>
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
<xsl:call-template name="headerRow" />
<xsl:apply-templates select="//product" />
</xsl:template>
<xsl:template name="headerRow">
<xsl:call-template name="rightpad">
<xsl:with-param name="fieldvalue" select="'sku'"/>
<xsl:with-param name="fieldsize" select="number(11)"/>
</xsl:call-template>
<xsl:call-template name="rightpad">
<xsl:with-param name="fieldvalue" select="'field'"/>
<xsl:with-param name="fieldsize" select="number(22)"/>
</xsl:call-template>
<xsl:text>value
</xsl:text>
</xsl:template>
<xsl:template match="product">
<xsl:for-each select="node()[local-name(.) != 'sku']">
<xsl:call-template name="rightpad">
<xsl:with-param name="fieldvalue" select="../sku"/>
<xsl:with-param name="fieldsize" select="number(11)"/>
</xsl:call-template>
<xsl:call-template name="rightpad">
<xsl:with-param name="fieldvalue" select="local-name(.)"/>
<xsl:with-param name="fieldsize" select="number(22)"/>
</xsl:call-template>
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template name="rightpad">
<xsl:param name="fieldvalue" select="string('')"/>
<xsl:param name="fieldsize" select="0"/>
<xsl:variable name="padded"
select="concat($fieldvalue, ' ')" />
<xsl:variable name="result"
select="substring($padded,1,$fieldsize)" />
<xsl:value-of select="$result"/>
</xsl:template>
</xsl:stylesheet>
XPathDocumemt x = new XPathDocument("yourdoc.xml");
XPathNavigator n = x.CreateNavigator();
XPathNodeIterator i = n.Select("root/product");
List<string> fields = new List<string>() { "PID_OWNER_SellerID", "EANCode", "DeliveryDays" }
using (TextWriter w = File.CreateText("c:\\yourfile.csv"))
{
w.WriteLine("sku, field, value");
while (i.MoveNext())
{
foreach (string field in fields)
{
w.WriteLine(string.Format("{0}, {1}, {2}", i.Current.SelectSingleNode("sku").value, field, i.Current.selectSingleNode(field).Value));
}
}
}
此樣式表將以指定的格式產生輸出:
<?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" encoding="UTF-8" omit-xml-declaration="yes"/>
<!--Spacing between column1 and column2 is 11 characters-->
<xsl:variable name="col1-spaces" select="' '" />
<!--Spacing between column2 and column3 is 22 characters-->
<xsl:variable name="col2-spaces" select="concat($col1-spaces, $col1-spaces)" />
<xsl:template match="/">
<!--Generate the heading row first, then apply templates-->
<xsl:text>sku</xsl:text>
<!--Add enough spaces after to align the next column-->
<xsl:value-of select="substring($col1-spaces, 3)"/>
<xsl:text>field</xsl:text>
<!--Add enough spaces after to align the next column-->
<xsl:value-of select="substring($col2-spaces, 5)"/>
<xsl:text>value </xsl:text>
<xsl:apply-templates />
</xsl:template>
<!--Do nothing with sku elements-->
<xsl:template match="sku" />
<!--For all elements that are children of product, except for sku, do this-->
<xsl:template match="product/*[not(self::sku)]">
<xsl:value-of select="preceding-sibling::sku"/>
<!--Calculate how many spaces are needed using the length of the value of sku -->
<xsl:value-of select="substring($col1-separator, string-length(preceding-sibling::sku))"/>
<xsl:value-of select="local-name()" />
<!--Calculate how many spaces are needed using the length of the name of the current element-->
<xsl:value-of select="substring($col2-separator, string-length(local-name()))"/>
<xsl:value-of select="." />
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.