我目前正在处理XML请求,并且我正在尝试创建一个在调用中具有多个同名子节点的Reply Document,所以我想要返回的是:
<Reply Document>
<ConfirmationItem name = "One">
<ItemDetail />
</ConfirmationItem>
<ConfirmationItem name = "Two">
<ItemDetail />
</ConfirmationItem>
...
<ConfirmationItem name = "Twenty">
<ItemDetail />
</ConfirmationItem>
</Reply Document>
我做了一些研究,发现了这个帖子:XmlReader AppendChild is not appending same child value,其中接受的答案是OP必须创建新的元素才能追加到最后而不是覆盖第一个元素。
我的原始代码如下,它从传入的请求创建XmlNode并将结果附加到XmlDocument本身:
//p_transdoc is the XmlDocument that holds all the items to process.
XmlNodeList nodelst_cnfrm = p_transdoc.SelectNodes("//OrderRequest");
foreach (XmlNode node in nodelst_cnfrm)
{
//this is just an XML Object
XmlNode node_cnfrm_itm = this.CreateElement("ConfirmationItem");
node_cnfrm_itm.Attributes.Append(this.CreateAttribute("name")).InnerText = p_transdoc.Attributes["name"].InnerText;
XmlNode node_itmdtl = this.CreateElement("ItemDetail");
node_cnfrm_itm.AppendChild(node_itmdtl);
//xml_doc is the return XML request
xml_doc.AppendChild(node_cnfrm_itm);
}
因此,在阅读该线程和答案之后,我尝试更改代码以使用每个传递的新XmlElement。
//p_transdoc is the XmlDocument that holds all the items to process.
XmlNodeList nodelst_cnfrm = p_transdoc.SelectNodes("//OrderRequest");
foreach (XmlNode node in nodelst_cnfrm)
{
XmlElement node_cnfrm_itm = new XmlElement();
node_cnfrm_itm = this.CreateElement("ConfirmationItem");
node_cnfrm_itm.Attributes.Append(this.CreateAttribute("name")).InnerText = p_transdoc.Attributes["name"].InnerText;
XmlElement node_itmdtl = new XmlElement();
node_itmdtl = this.CreateElement("ItemDetail");
node_cnfrm_itm.AppendChild(node_itmdtl);
//xml_doc is the return XML request
xml_doc.AppendChild(node_cnfrm_itm);
}
但这不仅不起作用,还会返回服务器错误。所以我来找你帮忙。现在这段代码只返回一个ConfirmationItem。我如何能够将ConfirmationItem附加到Document的末尾而不是覆盖它,以便能够返回尽可能多的数量?
(我应该指出,这段代码已经过大量格式化,以便于阅读,简化并减少混乱。任何印刷错误都纯粹是因为Asker在有效校对时的内部失败)。
答案 0 :(得分:1)
假设xml_doc是带有ConfirmationItems的xml,则需要使用新的XmlDocument创建XmlElements。 XmlDocument.CreateElement
。因此,我在这里使用Linq扩展方法OfType<>()
仅返回XmlElement类型的XmlNode对象。
// dummy data
XmlDocument p_transdoc = new XmlDocument();
p_transdoc.LoadXml(@"
<root name='rootAttribute'>
<OrderRequest name='one' />
<OrderRequest name='two' />
<OrderRequest name='three' />
</root>
");
XmlDocument xml_doc = new XmlDocument();
xml_doc.LoadXml("<ReplyDocument />");
foreach (var node in p_transdoc.SelectNodes("//OrderRequest").OfType<XmlElement>())
{
XmlElement node_cnfrm_itm = xml_doc.CreateElement("ConfirmationItem");
node_cnfrm_itm = xml_doc.DocumentElement.AppendChild(node_cnfrm_itm) as XmlElement;
node_cnfrm_itm.SetAttribute("name", node.GetAttribute("name"));
XmlElement node_itmdtl = xml_doc.CreateElement("ItemDetail");
node_itmdtl = node_cnfrm_itm.AppendChild(node_itmdtl) as XmlElement;
}
方法CreateElement
返回一个XmlElement,因此您可以使用方法SetAttribute
和GetAttribute
。
代码:p_transdoc.Attributes["name"].InnerText
似乎不对。如果要获取文档根元素的属性,则需要键入:p_transdoc.DocumentElement.GetAttribute("name")
如果您使用Linq to XML,IMO会更容易。
在Linq to XML中,这类似于(某些变量具有不同的名称):
// dummy data
var transDoc = XDocument.Parse(@"
<root name='rootAttribute'>
<OrderRequest name='one' />
<OrderRequest name='two' />
<OrderRequest name='three' />
</root>");
var xmlDoc = XDocument.Parse("<ReplyDocument />");
xmlDoc.Root.Add(
transDoc.Root.Elements("OrderRequest").Select(o =>
new XElement("ConfirmationElement",
new XAttribute("name", (string)o.Attribute("name")),
new XElement("ItemDetail"))));
两个示例输出:
<ReplyDocument>
<ConfirmationElement name="one">
<ItemDetail />
</ConfirmationElement>
<ConfirmationElement name="two">
<ItemDetail />
</ConfirmationElement>
<ConfirmationElement name="three">
<ItemDetail />
</ConfirmationElement>
</ReplyDocument>