2011-03-15 69 views
4

我目前正在處理一個XML請求,並且正在嘗試創建一個在調用中具有多個同名節點的回覆文檔,所以我試圖返回是:向XML文檔追加多個類似的XML節點

<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附加到文檔的末尾而不是覆蓋它,以便能夠返回與發送的數量相同的數量? (我應該指出,爲了便於閱讀,簡化和減少混亂,這些代碼已經被大量格式化,任何印刷錯誤純粹是因爲Asker在有效校對時發生的內部故障)。

+1

什麼樣的對象是 '這個'? – 2011-03-15 14:17:33

回答

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的,所以你可以使用的方法SetAttributeGetAttribute的方法。代碼: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> 
+0

非常感謝你的回覆。我將不得不對Linq to XML做更多的研究,以充分理解第二個例子。第一個例子,雖然我有問題,也許這是因爲我缺乏經驗。但是,我沒有看到你自己附加元素的位置。這是系統自動執行的事情嗎? – Gobbledigook 2011-03-15 16:01:19

+0

此外,只是想指出:p_transdoc.Attributes [「name」]。InnerText絕對不是最優雅的解決方案(我知道現在!:)),但它是可行的,至少在foreach的上下文中循環本身。它從OrderRequest節點本身獲取名稱屬性,因爲這是從p_transdoc預加載的,也就是說。的SelectNodes( 「// OrderRequest」);只想給你提供信息的目的:) – Gobbledigook 2011-03-15 16:09:26

+0

我創建了節點,並將其附加到單行中的文檔中:xml_doc.DocumentElement.AppendChild(xml_doc.CreateElement(「ConfirmationItem」));.爲了提高可讀性,您可以更改爲:var n = xml_doc.CreateElement(「ConfirmationItem」); n = xml_doc.DocumentElement.AppendChild(n); – 2011-03-15 16:43:29