我有一个XML文件,该文件已从Excel导出,可以满足我的需要。用XML来保存数据是一次操作,除一个问题外,它确实遇到了我的需要。
XML文件包含数千个“任务”条目,每个任务都列出了执行该任务所需的各种耗材。每个任务只能出现一次,尽管其中显然可以列出许多耗材。
问题是从Excel遇到的地方,如果一个任务需要3个耗材,则它会生成3次任务,每个任务只包含一个耗材。
因此,我需要将具有一项常见任务的耗材合并到一个任务中。这将是一次操作,并且数据将从此处开始以XML进行管理。
下面的XML示例:
<tasks>
<task>
<taskCode>123456</taskCode>
<taskName>Mow lawn</taskName>
<supplies>
<tool>
<id>Edge trimmer</id>
</tool>
</supplies>
</task>
<task>
<taskCode>123456</taskCode>
<taskName>Mow lawn</taskName>
<supplies>
<tool>
<id>Lawn mover</id>
</tool>
</supplies>
</task>
<task>
<taskCode>45678</taskCode>
<taskName>Paint wall</taskName>
<supplies>
<tool>
<id>Paint brush</id>
</tool>
</supplies>
</task>
</tasks>
在此示例中,我需要合并前两个任务,以便最终得到:
<tasks>
<task>
<taskCode>123456</taskCode>
<taskName>Mow lawn</taskName>
<supplies>
<tool>
<id>Edge trimmer</id>
<id>Lawn mover</id>
</tool>
</supplies>
</task>
<task>
<taskCode>45678</taskCode>
<taskName>Paint wall</taskName>
<supplies>
<tool>
<id>Paint brush</id>
</tool>
</supplies>
</task>
</tasks>
答案 0 :(得分:0)
为原始映射创建类,为新映射创建类,然后反序列化为原始类,为新类创建映射,并将其序列化为新格式。
答案 1 :(得分:0)
Linq to XML允许您进行GROUP BY查询。
var xdoc = XDocument.Parse("YOUR XML DATA");
var tasks = xdoc.Descendants("task")
.GroupBy
(
t => t.Element("taskCode").Value, // group on taskCode value
t => t,
(k, g) => new XElement // Make a new "task" element
(
"task",
new XElement("taskCode", k), // with the taskCode
g.Select(x => x.Element("taskName")).FirstOrDefault(), // taskName, just pick the first one
new XElement("supplies", g.Select(x => x.Element("supplies").Element("tool")).ToList()) // merge the "tools"
)
);
xdoc.Element("tasks").ReplaceNodes(tasks); // then inject updated nodes back in the xml
结果:
<tasks>
<task>
<taskCode>123456</taskCode>
<taskName>Mow lawn</taskName>
<supplies>
<tool>
<id>Edge trimmer</id>
</tool>
<tool>
<id>Lawn mover</id>
</tool>
</supplies>
</task>
<task>
<taskCode>45678</taskCode>
<taskName>Paint wall</taskName>
<supplies>
<tool>
<id>Paint brush</id>
</tool>
</supplies>
</task>
</tasks>
答案 2 :(得分:0)
如果您对XSLT 1.0解决方案感兴趣,则可以使用称为Muenchian分组的技术。当您想按task
对taskCode
元素进行分组时,首先要像这样定义一个键
<xsl:key name="tasks" match="task" use="taskCode" />
然后,要获取每个可能的taskCode首次出现的task
元素,您可以这样做
<xsl:template match="tasks">
<xsl:copy>
<xsl:apply-templates select="task[generate-id() = generate-id(key('tasks', taskCode)[1])]" />
</xsl:copy>
</xsl:template>
然后,您只需使用键在id
下添加所有额外的tool
元素。试试这个XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="tasks" match="task" use="taskCode" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="tasks">
<xsl:copy>
<xsl:apply-templates select="task[generate-id() = generate-id(key('tasks', taskCode)[1])]" />
</xsl:copy>
</xsl:template>
<xsl:template match="tool">
<xsl:copy>
<xsl:apply-templates select="key('tasks', ../../taskCode)/supplies/tool/id" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
请注意身份模板的使用,该模板用于复制不需要更改的元素。