I have an xElement data <a><item><item1/><item2/></item></a>
Need to replace item node with another node .
How can we achieve this?
I just need to replace item node with some other node say <b><b1/></b>
I want output as <a><b><b1/></b></a>
you could use ReplaceWith
xelementnode.ReplaceWith(new XElement(yournode));
Please find the below script, this is help you to replace the node
XElement xmlTree = new XElement("Students",
new XElement("Andrew", "Andrew Wilson"),
new XElement("Thomas", "Thomas Alwa"),
new XElement("Winston", "Winston GH"),
new XElement("Hary", "Hary Potter"),
new XElement("Jacky", "Jacky Elia")
);
XElement xel = xmlTree.Element("Winston");
xel.ReplaceWith(new XElement("Bill", "Bill Gate"));
Console.WriteLine(xmlTree);
Related
I try to rename any node starts with "NP" to "NP" in an XmlDocument. I only found this related questoin. based on the most up-voted answer I wrote:
XmlNodeList npNodeList = PSbank.SelectNodes("//*[starts-with(name(), 'NP')]");
foreach (XmlNode npNode in npNodeList)
{
// create new (renamed) Content node
XmlNode newNode = PSbank.CreateElement("NP");
// [if needed] copy existing Content children
newNode.InnerXml = npNode.InnerXml;
// replace existing Content node with newly renamed Content node
npNode.ParentNode.InsertBefore(newNode, npNode);
npNode.ParentNode.RemoveChild(npNode);
}
However, it seems it doesn't work in my case. When an NPX node contains other NPX nodes, the inner nodes are not replaced because the code manipulates XmlDocument and replaces the outer node with a new created node that contains the old innerXml.
Example Xml:
<S>
<NPC>
<NP> A </NP>
<NPA> B </NPA>
</NPC>
<NPD>
C
</NPD>
</S>
I look for a more general and elegant answer for such a problem.
I'd do this with LINQ to XML, it's a lot easier and cleaner. Firstly, it's generally a much nicer library, and secondly: XElement.Name is mutable.
var doc = XDocument.Parse(xml); // or use XDocument.Load
foreach (var element in doc.Descendants())
{
if (element.Name.LocalName.StartsWith("NP"))
{
element.Name = "NP";
}
}
See this fiddle for a working demo.
I have an XML file that contains multiple URLs for different image file sizes, and I'm trying to get a single url to load into a picture box. My issue is that the child nodes are named similarly, and the parent nodes are named similarly as well. For example, I want to pull the first medium image (ending in SL160_.jpg). See below for XML code
<Items>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL75_.jpg</URL>
</SmallImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL160_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL162_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
</Items>
I've tried using GetElementsByTag, as well as trying to call something like doc.SelectSingleNode("LargeImage").SelectSingleNode("URL").InnerText, and GetElementByID. All of these have given me an Object set to null reference exception.
What can I do to specify that I want the url from the first found MediumImage node?
Use LinqToXMLïĵIt is rather simple
string xml = #"<Items>
<SmallImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL._SL75_.jpg</URL>
</SmallImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.01_SL160_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
<MediumImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.02_SL162_.jpg</URL>
</MediumImage>
<LargeImage>
<URL>http://ecx.images-amazon.com/images/I/51TAL%2Bn7AqL.jpg</URL>
</LargeImage>
</Items>";
XElement root = XElement.Parse(xml);
var ele = root.Elements("MediumImage").Where(e => e.Element("URL").Value.EndsWith("SL160_.jpg")).FirstOrDefault();
Console.WriteLine(ele);
In addition to Sky Fang's answer, I think the OP wants this:
var firstMedImg = root.Elements("MediumImage").First();
var imgUrl = firstMedImg.Element("URL").Value;
XmlDocument doc = new XmlDocument();
// PATH TO YOUR DOCUMENT
doc.Load("daco.xml");
// Select LIST ALL ELEMENTS SmallImage,MediumImage,LargeImage
XmlNodeList listOfAllImageElements = doc.SelectNodes("/Items/*");
foreach (XmlNode imageElement in listOfAllImageElements)
{
// Select URL ELEMENT
XmlNode urlElement= node.SelectSingleNode("URL");
System.Console.WriteLine(urlElement.InnerText);
}
Console.ReadLine();
If you want to select multiple url's
XmlDocument doc = new XmlDocument();
// PATH TO YOUR DOCUMENT
doc.Load("daco.xml");
// Select LIST ALL ELEMENTS SmallImage,MediumImage,LargeImage
XmlNodeList listOfAllImageElements = doc.SelectNodes("/Items/*");
foreach (XmlNode imageElement in listOfAllImageElements)
{
// Select URL's ELEMENTs
XmlNodeList listOfAllUrlElements = imageElement.SelectNodes("URL");
foreach (XmlNode urlElement in listOfAllUrlElements)
{
System.Console.WriteLine(urlElement.InnerText);
}
}
Console.ReadLine();
if you have specific namespace in your xml file
XmlDocument doc = new XmlDocument();
doc.Load("doc.xml");
XmlNamespaceManager man = new XmlNamespaceManager(doc.NameTable);
// reaplace http://schemas.microsoft.com/vs/2009/dgml with your namespace
man.AddNamespace("x", "http://schemas.microsoft.com/vs/2009/dgml");
// next you have to use x: in your path like this
XmlNodeList node = doc.SelectNodes("/x:Items/x:*, man);
I am creating XML document by reading some objects and adding them to proper place (inside xml tree structure). To be able to add it to proper place I need parent XmlNode so I could call parentNode.AppendChild(node);
How can I get XmlNode object if I know value of one of its attributes?
XmlDocument dom = new XmlDocument();
XmlNode parentNode = null;
XmlNode node = dom.CreateElement(item.Title); //item is object that I am writing to xml
XmlAttribute nodeTcmUri = dom.CreateAttribute("tcmUri");
nodeTcmUri.Value = item.Id.ToString();
node.Attributes.Append(nodeTcmUri);
parentNode = ??? - how to get XML node if I know its "tcmUri" attribute value (it is unique value, no other node has same "tcmUri" attribute value)
You can do this using SelectSingleNode function and xpath query as below
XmlNode parentNode = dom.SelectSingleNode("descendant::yournodename[#tcmUri='" + item.Id.ToString() + "']");
Where yournodename has to be replaced with the node name of the parent elements
Try this
XmlDocument doc = new XmlDocument();
doc.LoadXml(content);
XmlNodeList list = doc.SelectNodes("mynode");
foreach (XmlNode item in list)
{
if (item.Attributes["tcmUri"].Value == some_value)
{
// do what you want, item is the element you are looking for
}
}
Use following code:
var nodeList = doc.SelectNodes("<Node Name>[#tcmUri = \"<Value>\"]");
if(list.Count>0)
parentNode = list[0];
Replace <Node Name> with the node name which you want to make the parent node.
Replace the <Value> with the value of tcmUri attribute of the Node which you want to make the parent node.
XPath is your friend :
string xpath = String.Format("//parentTag[#tcmUri='{0}']", "tcmUriValueHere");
//or in case parent node name (parentTag) may varies
//you can use XPath wildcard:
//string xpath = String.Format("//*[#tcmUri='{0}']", "tcmUriValueHere");
parentNode = dom.SelectSingleNode(xpath)
I have a XML file which contains about 850 XML nodes. Like this:
<NameValueItem>
<Text>Test</Text>
<Code>Test</Code>
</NameValueItem>
........ 849 more
And I want to add a new Childnode inside each and every Node. So I end up like this:
<NameValueItem>
<Text>Test</Text>
<Code>Test</Code>
<Description>TestDescription</Description>
</NameValueItem>
........ 849 more
I've tried the following:
XmlDocument doc = new XmlDocument();
doc.Load(xmlPath);
XmlNodeList nodes = doc.GetElementsByTagName("NameValueItem");
Which gives me all of the nodes, but from here am stuck(guess I need to iterate over all of the nodes and append to each and every) Any examples?
You need something along the lines of this example below. On each of your nodes, you need to create a new element to add to it. I assume you will be getting different values for the InnerText property, but I just used your example.
foreach (var rootNode in nodes)
{
XmlElement element = doc.CreateElement("Description");
element.InnerText = "TestDescription";
root.AppendChild(element);
}
You should just be able to use a foreach loop over your XmlNodeList and insert the node into each XmlNode:
foreach(XmlNode node in nodes)
{
node.AppendChild(new XmlNode()
{
Name = "Description",
Value = [value to insert]
});
}
This can also be done with XDocument using LINQ to XML as such:
XDocument doc = XDocument.Load(xmlDoc);
var updated = doc.Elements("NameValueItem").Select(n => n.Add(new XElement() { Name = "Description", Value = [newvalue]}));
doc.ReplaceWith(updated);
If you don't want to parse XML using proper classes (i.e. XDocument), you can use Regex to find a place to insert your tag and insert it:
string s = #"<NameValueItem>
<Text>Test</Text>
<Code>Test</Code>
</NameValueItem>";
string newTag = "<Description>TestDescription</Description>";
string result = Regex.Replace(s, #"(?<=</Code>)", Environment.NewLine + newTag);
but the best solution is Linq2XML (it's much better, than simple XmlDocument, that is deprecated at now).
string s = #"<root>
<NameValueItem>
<Text>Test</Text>
<Code>Test</Code>
</NameValueItem>
<NameValueItem>
<Text>Test2</Text>
<Code>Test2</Code>
</NameValueItem>
</root>";
var doc = XDocument.Load(new StringReader(s));
var elms = doc.Descendants("NameValueItem");
foreach (var element in elms)
{
element.Add(new XElement("Description", "TestDescription"));
}
var text = new StringWriter();
doc.Save(text);
Console.WriteLine(text);
I have an xml that looks like this
<words>
<word>word1</word>
<word>word2</word>
<word>word3</word>
<word>word4</word>
</words>
I would like to loop through the "word" tags and just output the innertext for now.
how would I do this?
here is what i am doing now but is says the list of nodes count is 1
string _badWordFileDocPath = //my file path;
XmlDocument badWordDoc = new XmlDocument();
badWordDoc.Load(_badWordFileDocPath);
XmlElement root = badWordDoc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("/words");
foreach(XmlNode node in nodes)
{
Console.WriteLine(node.InnerText);
}
Thanks!
You are selecting the root words node itself, rather than the child word nodes. Add /word to your XPath:
XmlNodeList nodes = root.SelectNodes("/words/word");
You need to move down the node tree one more layer:
foreach(XmlNode node in nodes)
{
XmlNodeList innerNodes = node.SelectNodes("/word");
foreach(Xmlnode innerNode in innerNodes )
{
Console.WriteLine(innerNode.InnerText);
}
}
I'd recommend using the classes in System.Xml.Linq for this task:
XElement wordsElement = XElement.Parse(yourXmlText);
var words = from w in wordsElement.Elements("word")
select w.Value;
You are missing /word in your XPath.
You can also use Linq (XDocument) to fetch the data.