c# - Transforming repeating group into several text lines -
i wanted transform repeating group sample xml 2 delimited text lines. here current code version:
string orderxml = @"<?xml version='1.0' encoding='utf-8'?> <order id='79223510'> <status>new</status> <shipmethod>standard international</shipmethod> <tocity>tokyo</tocity> <items> <item> <sku>sku-1234567890</sku> <quantity>1</quantity> <price>99.95</price> </item> <item> <sku>sku-1234567899</sku> <quantity>1</quantity> <price>199.95</price> </item> </items> </order>"; stringreader str = new stringreader(orderxml); var xslt = new xmltextreader(new stringreader( @"<?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='no'/>" + "<!-- new line character variable -->" + "<xsl:variable name='newline'>" + "<xsl:text> </xsl:text>" + "</xsl:variable>" + "<xsl:variable name='empty'>" + "<xsl:text></xsl:text>" + "</xsl:variable>" + "<xsl:template match='/'>" + "<xsl:for-each select='order'>" + "<xsl:value-of select='@id'/>|" + "<xsl:value-of select='status'/>|" + "<xsl:value-of select='shipmetod'/>|" + "<xsl:value-of select='tocity'/>|" + "<xsl:value-of select='$newline'/>" + "</xsl:for-each>" + "<xsl:for-each select='order/items/item'>" + "<xsl:value-of select='sku'/>|" + "<xsl:value-of select='quantity'/>|" + "<xsl:value-of select='price'/>|" + "<xsl:value-of select='$newline'/>" + "</xsl:for-each>" + "</xsl:template>" + "</xsl:stylesheet>" )); var xdoc = new xpathdocument(str); var xtr = new system.xml.xsl.xslcompiledtransform(); xtr.load(xslt); stringbuilder sb = new stringbuilder(); stringwriter writer = new stringwriter(sb); xtr.transform(xdoc, null, writer); string[] lines = sb.tostring().split(new string[] {"\n"}, stringsplitoptions.removeemptyentries); lines.tolist().foreach(system.console.write);
this code produces following output:
79223510|new||tokyo| sku-1234567890|1|99.95| sku-1234567899|1|199.95|
and wanted produce following one:
79223510|new||tokyo|sku-1234567890|1|99.95| 79223510|new||tokyo|sku-1234567899|1|199.95|
by using xsl transformation. please advise.
p.s. added xsl in text form easier reading:
@<?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='no'/> <!-- new line character variable --> <xsl:variable name='newline'> <xsl:text> </xsl:text> </xsl:variable> <xsl:variable name='empty'> <xsl:text></xsl:text> </xsl:variable> <xsl:template match='/'> <xsl:for-each select='order'> <xsl:value-of select='@id'/>| <xsl:value-of select='status'/>| <xsl:value-of select='shipmetod'/>| <xsl:value-of select='tocity'/>| <xsl:value-of select='$newline'/> </xsl:for-each> <xsl:for-each select='order/items/item'> <xsl:value-of select='sku'/>| <xsl:value-of select='quantity'/>| <xsl:value-of select='price'/>| <xsl:value-of select='$newline'/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
you making few mistakes:
- you using 2 separate for-each loops rather loop in loop, first line of output
order
element, , next 2item
elements. (actually don't need loops. solution below.) - you misspelled
shipmetod
, 1 of fields mistakenly blank. - you don't have method in place escape
|
values may present in field values. (my solution doesn't solve problem since i'm not sure want it.)
a better solution use template matching , string-concatenation.
<xsl:stylesheet version="1.0" xmlns:xsl='http://www.w3.org/1999/xsl/transform'> <xsl:output method="text" indent="no" media-type="text/plain" /> <xsl:variable name='newline'><xsl:text> </xsl:text></xsl:variable> <xsl:variable name='delimiter'>|</xsl:variable> <!-- default, don't copy nodes output --> <xsl:template match="node()|@*"><xsl:apply-templates select="node()|@*"/></xsl:template> <xsl:template match="/order/items/item"><xsl:value-of select="concat( ../../@id, $delimiter, ../../status, $delimiter, ../../shipmethod, $delimiter, ../../tocity, $delimiter, sku, $delimiter, quantity, $delimiter, price, $delimiter, $newline)"/></xsl:template> </xsl:stylesheet>
this produces following output:
79223510|new|standard international|tokyo|sku-1234567890|1|99.95| 79223510|new|standard international|tokyo|sku-1234567890|1|199.95|
Comments
Post a Comment