问题
Here is a tricky bit of situation. I have a webservice that returns an XML document. This XML document has a root element that is called <Entities .... > The Entities element has child elements called <Article..>. I need to modify one of the child elements of Article and "PUT" each article element back to the webservice. The reason why I can not post the whole document with Entities is because the webservice does not recognize the Entities as an object and I can not perform an update operation on it.
Below is the structure of the document received:
<Entities>
<Article id="1">
<Permissions>
<Sla id="1">
<name> first sla </name>
</Sla>
</Permissions>
</Article>
<Article id="2">
<Permissions>
<Sla id="2">
<name> second sla </name>
</Sla>
</Permissions>
</Article>
</Entities>
Below is the code that I have used to do the trick but I can fetch the Sla element. What I need to do is to get the Sla elements in each article and run a check against its id attribute. If the check comes true, I need to remove that Sla element along with all of its child elements. This is what I have done so far:
int pageNumber = 1;
bool entities = true;
while (entities)
{
url = "www.myurl.com";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "Get";
HttpWebResponse rep = (HttpWebResponse)req.GetResponse();
doc.Load(rep.GetResponseStream());
rep.Close();
if (doc != null)
{
XmlNodeList nodes = doc.SelectNodes("/Entities/Article");
foreach (XmlNode node in nodes)
{
XmlNode Slanode = null;
try
{
Slanode = doc.SelectSingleNode("Permissions/Sla[@id='" + sla.ToString() + "']");
Slanode.ParentNode.RemoveChild(node);
string finalXML = doc.OuterXml;
HttpWebRequest reqToUpdate = (HttpWebRequest)WebRequest.Create(url);
reqToUpdate.ContentType = "text/xml; encoding=UTF-8";
reqToUpdate.Method = "PUT";
byte[] bytes = new UTF8Encoding().GetBytes(finalXML);
reqToUpdate.ContentLength = bytes.Length;
Stream data = reqToUpdate.GetRequestStream();
data.Write(bytes, 0, bytes.Length);
data.Close();
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
}
pageNumber++;
}
else
entities = false;
}
}
I cant get the code to work because when I reach the
Slanode = doc.SelectSingleNode("Permissions/Sla[@id='" + sla.ToString() + "']");
it does not populate the Slanode and it returns null, when I checked the nodes in debug mode, the list was showing the following error:
Only one top level element is allowed in an XML document. Error processing resource
any help would be greatly appreciated.
Thanks
回答1:
Path is wrong
Slanode = doc.SelectSingleNode("Permissions/Sla[@id='" + sla.ToString() + "']");
should be
Slanode = node.SelectSingleNode("Permissions/Sla[@id='" + sla.ToString() + "']");
I think.
回答2:
I'm going to re-write that with XElement, hopefully that works for you as XElement is what I understand.
First get the Article to remove:
XElement root = XElement.Load(stream);
XElement articleToRemove = root.XPathSelectElement("//Article[Permissions/Sla/@id='"+sla.ToString()+"']");
if(null != articleToRemove)
articleToRemove.Remove();
To make the loop readable, create a Put function:
private void Put(XElement article)
{
Stream data = null;
try
{
string finalXML = article.ToString(SaveOptions.DisableFormatting);
HttpWebRequest reqToUpdate = (HttpWebRequest)WebRequest.Create(url);
reqToUpdate.ContentType = "text/xml; encoding=UTF-8";
reqToUpdate.Method = "PUT";
byte[] bytes = new UTF8Encoding().GetBytes(finalXML);
reqToUpdate.ContentLength = bytes.Length;
data = reqToUpdate.GetRequestStream();
data.Write(bytes, 0, bytes.Length);
}
catch (Exception error)
{
MessageBox.Show(error.Message);
}
finally
{
if (null != data)
data.Close();
}
}
Then get the rest of the articles and upload them:
root.Descendants("Article").ToList().ForEach(a => Put(a));
Edit: To use XPath with XElement you need to use the following using:
using System.Xml.XPath;
来源:https://stackoverflow.com/questions/11706179/fetching-and-modifying-the-child-elements-in-an-xml-document