将重复组转换为多个文本行 [英] Transforming repeating group into several text lines
本文介绍了将重复组转换为多个文本行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我想将示例 XML 中的重复组转换为两个分隔的文本行.这是我当前的代码版本:
I wanted to transform repeating group from the sample XML into two delimited text lines. Here is my 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 currently produces the following output:
79223510|new||Tokyo|
SKU-1234567890|1|99.95|
SKU-1234567899|1|199.95|
我希望它产生以下内容:
and I wanted it to produce the following one:
79223510|new||Tokyo|SKU-1234567890|1|99.95|
79223510|new||Tokyo|SKU-1234567899|1|199.95|
仅使用 XSL 转换.请指教.
by just using XSL transformation. Please advise.
附言以文本形式添加了 XSL 以便于阅读:
P.S. Added XSL in a text form for 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>
推荐答案
你犯了几个错误:
- 您使用了两个单独的 for-each 循环而不是循环中的循环,因此您的第一行输出来自
Order
元素,接下来的两个来自Item
元素.(实际上您不需要任何循环.解决方案如下.) - 您拼错了
ShipMetod
,因此您的一个字段错误地为空. - 您没有任何方法可以转义字段值中可能存在的任何
|
值.(我的解决方案没有解决这个问题,因为我不确定你想怎么做.)
- You are using two separate for-each loops rather than a loop in a loop, so your first line of output is from the
Order
element, and the next two are from theItem
elements. (Actually you don't need any loops. Solution below.) - You misspelled
ShipMetod
, so one of your fields is mistakenly blank. - You don't have any method in place to escape any
|
values that may be present in the field values. (My solution doesn't solve this problem since I'm not sure what you want to do about it.)
更好的解决方案是使用模板匹配和字符串连接.
A better solution is to use template matching and 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>
<!-- by default, don't copy any nodes to 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>
这会产生以下输出:
79223510|new|Standard International|Tokyo|SKU-1234567890|1|99.95|
79223510|new|Standard International|Tokyo|SKU-1234567890|1|199.95|
这篇关于将重复组转换为多个文本行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文