我一直在努力应对这种转变,也许,除了我没有多少xslt练习之外,这里的某些人可以解决一些问题。使用xml
<?xml version="1.0" encoding="utf-8"?>
<recipes version="1.0">
<name language="en">195P 290000
000015 000010</name>
<recipe size="small">
<subsequence name="START">
<TMP> 90</TMP>
<DV> 0</DV>
<LG> 00FF0000</LG>
<CB> 0000FF00</CB>
<TS> 000000FF</TS>
<BS> 00320A00</BS>
</subsequence>
<subsequence name="FR">
<FWV>453</FWV>
<RWV>232</RWV>
<AP>21</AP>
</subsequence>
</recipe>
<recipe size="medium">
<subsequence name="START">
<TMP>215</TMP>
<DV> 0</DV>
<LG> 00060000</LG>
<CB> 00969696</CB>
<TS> 00191919</TS>
<BS> 00060606</BS>
</subsequence>
<subsequence name="FR">
<FWV>357</FWV>
<RWV>0</RWV>
<AP>0</AP>
</subsequence>
<subsequence name="VC">
<PS>29</PS>
<TM>5</TM>
<AP>0</AP>
</subsequence>
<subsequence name="FR">
<FWV> 0</FWV>
<RWV>45</RWV>
<AP>15</AP>
</subsequence>
<subsequence name="PG">
<PS>20</PS>
<TM>27</TM>
<LG>00060000</LG>
<CB>00040404</CB>
<TS>00040404</TS>
<BS>00202020</BS>
</subsequence>
<subsequence name="BO">
<BT>4</BT>
</subsequence>
</recipe>
<recipe size="large">
<subsequence name="FR">
<FWV>33357</FWV>
<RWV>0</RWV>
<AP>0</AP>
</subsequence>
<subsequence name="VC">
<PS>29</PS>
<TM>5</TM>
<AP>0</AP>
</subsequence>
<subsequence name="FR">
<FWV> 2222</FWV>
<RWV>333</RWV>
<AP>15</AP>
</subsequence>
<subsequence name="PG">
<PS>20</PS>
<TM>27</TM>
<LG>00060000</LG>
<CB>00040404</CB>
<TS>00040404</TS>
<BS>00202020</BS>
</subsequence>
<subsequence name="BO">
<BT>4</BT>
</subsequence>
</recipe>
</recipes>
你可以说每个大小都有一个开始序列,但除此之外,它是一个变量子序列,其中FR,VC,PR,BT属性以任何顺序发生。我无法想象的是如何将变换变成像
这样的变形<?xml version="1.0" encoding="utf-8"?>
<recipes version="1.0">
<name language="en">195P 290000 000015 000010</name>
<subsequence name="START">
<small>
<TMP> 90</TMP>
<DV> 0</DV>
<LG> 00FF0000</LG>
<CB> 0000FF00</CB>
<TS> 000000FF</TS>
<BS> 00320A00</BS>
</small>
<medium>
<TMP>215</TMP>
<DV> 0</DV>
<LG> 00060000</LG>
<CB> 00969696</CB>
<TS> 00191919</TS>
<BS> 00060606</BS>
</medium>
<large>
..values
</large>
</subsequence>
<subsequence name="FR">
<small>
...values
</small>
<medium>
..values
</medium>
<large>
..values
</large>
</subsequence>
<subsequence name="VC">
<small>
...values (again if any
</small>
<medium>
..values
</medium>
<large>
..values
</large>
</subsequence>
<subsequence name="FR">
<small>
...values
</small>
<medium>
..values
</medium>
<large>
..values
</large>
</subsequence>
..and so on
</recipes>
当然,开始很简单,但在那之后我就失去了理智。我需要组合下一个兄弟值(如果它存在)并且与文档顺序中的其他兄弟值相同。更多如果 大订单是FR VC PG和中等订单是FR VC PG我会将它们组合在一起如果它们不相同我会为值引入零。 IE如果第一个大的是FR而且第一个大的是VC,我会以任何顺序取一个,因为无论如何都会有零。
我已经放弃尝试使用XSLT来解决这个问题,但是想知道它是否有可能,因为它将到目前为止清理代码并允许单个对象模型被序列化/反序列化。
答案 0 :(得分:0)
实际上在XSLT中相对容易。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:key name="kSubsequenceByName" match="subsequence" use="@name" />
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="recipe">
<xsl:apply-templates select="node()" />
</xsl:template>
<xsl:template match="subsequence">
<xsl:variable name="myGroup" select="key('kSubsequenceByName', @name)" />
<xsl:if test="generate-id() = generate-id($myGroup)">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="$myGroup" mode="translate" />
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="subsequence" mode="translate">
<xsl:element name="{../@size}">
<xsl:apply-templates select="node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
为您提供输入样本:
<recipes version="1.0">
<name language="en">195P 290000
000015 000010</name>
<subsequence name="START">
<small>
<TMP>90</TMP>
<DV>0</DV>
<LG>00FF0000</LG>
<CB>0000FF00</CB>
<TS>000000FF</TS>
<BS>00320A00</BS>
</small>
<medium>
<TMP>215</TMP>
<DV>0</DV>
<LG>00060000</LG>
<CB>00969696</CB>
<TS>00191919</TS>
<BS>00060606</BS>
</medium>
</subsequence>
<subsequence name="FR">
<medium>
<FWV>357</FWV>
<RWV>0</RWV>
<AP>0</AP>
</medium>
<medium>
<FWV>0</FWV>
<RWV>45</RWV>
<AP>15</AP>
</medium>
</subsequence>
<subsequence name="VC">
<medium>
<PS>29</PS>
<TM>5</TM>
<AP>0</AP>
</medium>
</subsequence>
<subsequence name="PG">
<medium>
<PS>20</PS>
<TM>27</TM>
<LG>00060000</LG>
<CB>00040404</CB>
<TS>00040404</TS>
<BS>00202020</BS>
</medium>
</subsequence>
<subsequence name="BO">
<medium>
<BT>4</BT>
</medium>
</subsequence>
.
.
.
.
</recipes>
要知道(或阅读)的概念:
<xsl:key>
和Muenchian分组答案 1 :(得分:0)
这是使用xsl:for-each-group
而不是muenchian分组的XSLT 2.0选项。
XML输入(已修改为格式正确)
<recipes version="1.0">
<name language="en">195P 290000
000015 000010</name>
<recipe size="small">
<subsequence name="START">
<TMP> 90</TMP>
<DV> 0</DV>
<LG> 00FF0000</LG>
<CB> 0000FF00</CB>
<TS> 000000FF</TS>
<BS> 00320A00</BS>
</subsequence>
</recipe>
<recipe size="medium">
<subsequence name="START">
<TMP>215</TMP>
<DV> 0</DV>
<LG> 00060000</LG>
<CB> 00969696</CB>
<TS> 00191919</TS>
<BS> 00060606</BS>
</subsequence>
<subsequence name="FR">
<FWV>357</FWV>
<RWV>0</RWV>
<AP>0</AP>
</subsequence>
<subsequence name="VC">
<PS>29</PS>
<TM>5</TM>
<AP>0</AP>
</subsequence>
<subsequence name="FR">
<FWV> 0</FWV>
<RWV>45</RWV>
<AP>15</AP>
</subsequence>
<subsequence name="PG">
<PS>20</PS>
<TM>27</TM>
<LG>00060000</LG>
<CB>00040404</CB>
<TS>00040404</TS>
<BS>00202020</BS>
</subsequence>
<subsequence name="BO">
<BT>4</BT>
</subsequence>
</recipe>
<recipe size="large">
.
.
.
.
</recipe>
</recipes>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:apply-templates select="@*|node() except recipe"/>
<xsl:for-each-group select="recipe/subsequence" group-by="@name">
<xsl:variable name="name" select="current-grouping-key()"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="/*/recipe[subsequence/@name=$name]" group-by="@size">
<xsl:element name="{current-grouping-key()}">
<xsl:apply-templates select="subsequence[@name=$name and not(preceding-sibling::subsequence/@name=$name)]/*"/>
</xsl:element>
</xsl:for-each-group>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
XML输出
<recipes version="1.0">
<name language="en">195P 290000
000015 000010</name>
<subsequence name="START">
<small>
<TMP> 90</TMP>
<DV> 0</DV>
<LG> 00FF0000</LG>
<CB> 0000FF00</CB>
<TS> 000000FF</TS>
<BS> 00320A00</BS>
</small>
<medium>
<TMP>215</TMP>
<DV> 0</DV>
<LG> 00060000</LG>
<CB> 00969696</CB>
<TS> 00191919</TS>
<BS> 00060606</BS>
</medium>
</subsequence>
<subsequence name="FR">
<medium>
<FWV>357</FWV>
<RWV>0</RWV>
<AP>0</AP>
</medium>
</subsequence>
<subsequence name="VC">
<medium>
<PS>29</PS>
<TM>5</TM>
<AP>0</AP>
</medium>
</subsequence>
<subsequence name="PG">
<medium>
<PS>20</PS>
<TM>27</TM>
<LG>00060000</LG>
<CB>00040404</CB>
<TS>00040404</TS>
<BS>00202020</BS>
</medium>
</subsequence>
<subsequence name="BO">
<medium>
<BT>4</BT>
</medium>
</subsequence>
</recipes>
答案 2 :(得分:0)
所以这就是我想出来的,我知道它并不完美......如果有人有更好的选择,我很乐意看到它。
//function for applying annotations similar to MSDN example (shame on me)
static XElement XForm(XElement source)
{
if (source.Annotation<XAttribute>() != null)
{
XAttribute anno = source.Annotation<XAttribute>();
return new XElement( source.Name, anno, source.Attributes(), source.Nodes());
}
else
{
return new XElement(source.Name,
source.Attributes(),
source.Nodes().Select(n =>
{
XElement el = n as XElement;
if (el == null)
return n;
else
return XForm(el);
}
)
);
}
}
XElement root = XElement.Load(".xml");
root.DescendantNodes().OfType<XComment>().Remove();
int subIncrement = 0;
foreach (var el in root.Descendants("subsequence"))
{
if (el.Attribute("name").Value == "START") { subIncrement = 0; }
el.AddAnnotation(new XAttribute("key", el.FirstAttribute.Value + subIncrement));
subIncrement += 1;
}
XElement newRoot = XForm(root);
var transform = new XElement("recipe", from data in
(from seq in newRoot.Descendants("subsequence")
select new XElement(seq.Attribute("key").Value
,new XElement(seq.Ancestors().First().FirstAttribute.Value
,seq.Nodes()
)
)
)
group data by data.Name.ToString() into groups
select new XElement((string)groups.Key , groups.Nodes()));