将重复组转换为多个文本行 [英] Transforming repeating group into several text lines

查看:51
本文介绍了将重复组转换为多个文本行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将示例 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>&#13;&#10;</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>&#13;&#10;</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>

推荐答案

你犯了几个错误:

  1. 您使用了两个单独的 for-each 循环而不是循环中的循环,因此您的第一行输出来自 Order 元素,接下来的两个来自 Item 元素.(实际上您不需要任何循环.解决方案如下.)
  2. 您拼错了 ShipMetod,因此您的一个字段错误地为空.
  3. 您没有任何方法可以转义字段值中可能存在的任何 | 值.(我的解决方案没有解决这个问题,因为我不确定你想怎么做.)
  1. 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 the Item elements. (Actually you don't need any loops. Solution below.)
  2. You misspelled ShipMetod, so one of your fields is mistakenly blank.
  3. 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>&#13;&#10;</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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆