I have a C# application that uses a button to generate a file. Currently, I want to use C# to extract out contents from the XML file and pass it as a string. For example in my XML file, I have a tag name. I want to use c# to extract the name from the XML file. How should I go about achieving it? Below is the sample code I have currently. The entire process must be carried out using a button click.
private void button1_Click(object sender, EventArgs e)
{
XElement xml = XElement.Load("C:\\Windows 7.xml");
IEnumerable<XElement> propertyIDs = xml.Descendants("PropertyId");
foreach (XElement child in xml.Elements())
{
XElement row = child.Element("my:VM_Name");
string test = xml.ToString();
Console.WriteLine(test);
}
}
Please access this link to view my xml file: http://pastebin.com/NKhBb4Zh
I rewrote your example and changed it to make use of the XmlDocument class. As there is the my Namespace I had to add a NameSpaceManager. using this you may even select a spefic node.
string url = #"e:\temp\data.xml";
XmlDocument doc = new System.Xml.XmlDocument();
doc.Load(url);
XmlElement docElement = doc.DocumentElement;
/// loop through all childNodes
foreach (XmlNode childNode in docElement.ChildNodes)
{
Console.WriteLine(childNode.Name + ": " + childNode.InnerText);
}
XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("my", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2011-05-27T03:57:48");
/// use the given XmlNamespaceManager to select a specific element
XmlNode node = docElement.SelectSingleNode("my:VM_DiskSize", mgr);
/// use innerText for node text and value for attributes only
Console.WriteLine("\n" + node.Name + ": " + node.InnerText);
hth
The comments you added to your question were very helpful. In particular:
I added this code:
XElement name = xml.Element("my:VM_Name");
string test = xml.ToString();
Console.WriteLine(test);
But I am still unable to extract out Windows 7 from the XML tag
And:
i get this error The ':' character, hexadecimal value 0x3A, cannot be included in a name.
Let's start with the error first. You cannot pass to the Element method an ns:name pair as you've done. With this API, the namespace (ns) must be supplied programatically via the XName type. So instead, that line should read:
XElement name = xml.Element(XName.Get("VM_Name", "my"));
Here we pass the qualified name as an actual XName and not as a colon-delimited string as it originates. Pay attention to the order; the namespace comes second using this syntax.
Now, once you have done all this, the other line in which you have a problem is:
string test = xml.ToString();
Here, xml refers to your root XML node whereas what you actually want is, presumably, the element for which you just queried: xml.Element(XName.Get("VM_Name", "my")). Furthermore, to get the text contents of that node, you should use the Value property. I suspect what you really want is:
string test = name.Value;
Related
I have a requirement to edit and save- precisely replace a text in an xml (within the c# project) with a value from arguments and save in temp location. The value is replaced and saved in location, but it adds some characters- [] and hence when i use the xml in another application as input, it is shown as incorrect xml! Even when i remove the extra character and save and rerun it shows the same error. However when i remove the extra character and paste the whole xml into a new file it works fine! I dont understand whats the issue. Have pasted my code below:
{
parameterFileName = "test";
tempPath = Path.GetTempPath() + parameterFileName + DateTime.Now.ToString("dd-MM-yyyy_hh-mm-ss") + ".xml";
XmlDocument xdoc = GetParameterXML(parameterFileName);
XmlNode root = xdoc.DocumentElement;
XmlNode node = xdoc.DocumentElement.SelectSingleNode(#"/root/inputParameters");
XmlNode childNode = node.ChildNodes[0];
if (childNode is XmlCDataSection)
{
XmlCDataSection cdataSection = childNode as XmlCDataSection;
if (cdataSection.Value.Contains("ID_VALUE"))
{
cdataSection.Value = cdataSection.Value.Replace("ID_VALUE", id);
}
}
xdoc.Save(tempPath);
}
public static XmlDocument GetParameterXML(string parameterFileName)
{
var sDllPath = AppDomain.CurrentDomain.BaseDirectory;
XmlDocument xDoc = new XmlDocument();
xDoc.Load(sDllPath + "\\Templates\\" + parameterFileName + ".xml");
return xDoc;
}
When you parse Xml Document by using XmlDocument with DTD then empty Internal Subset means Square Brackets [] is automatically inserted.
public static XmlDocument GetParameterXML(string parameterFileName)
{
var sDllPath = AppDomain.CurrentDomain.BaseDirectory;
XmlDocument xDoc = new XmlDocument();
xDoc.Load(sDllPath + "\\Templates\\" + parameterFileName + ".xml");
if (xDoc.DocumentType != null)
{
var name = xDoc.DocumentType.Name;
var publicId = xDoc.DocumentType.PublicId;
var systemId = xDoc.DocumentType.SystemId;
var parent = xDoc.DocumentType.ParentNode;
var documentTypeWithNullInternalSubset = xDoc.CreateDocumentType(name, publicId, systemId, null);
parent.ReplaceChild(documentTypeWithNullInternalSubset, xDoc.DocumentType);
}
return xDoc;
}
Does it matter?
No this does not matter. but its a well formed XML if your XML doesn't contain any internal subset then it represent as blank square brackets []. it means that your xml doesn't contain any internal subset.
While parsing xml with XDocument with no internal subset then XDocument append blank square brackets [] instead of display nothing in DOCTYPE.
What does an empty internal subset do?
The basic purpose of an internal entity is to get rid of typing same content (like the name of the organization) again and again. And instead, we can define an internal entity to contain the text and then only you need to use the entity where you want to insert the text. Because the entity is expanded by the parser, you can be assured that you'll get the same text in every location. The parser will also catch if you misspell an entity name.
You can read more about Internal Subset here
I am building an xml document and I have declared the namespace at the very top.
<Root xmlns="http://www.omg.org/space/xtce" xmlns:xtce="http://www.omg.org/space/xtce" ...>
At some arbitrary level below I want to AppendChild with an element created from a string. My goal is to end up with a document that contains that element without the xmlns AT ALL.
This is the closest I have gotten-
string someElementStr = "<SomeElement name="foo"><SubElement name="bar" /></SomeElement>";
XmlDocumentFragment node = doc.CreateDocumentFragment();
node.InnerXml = someElementStr;
someXmlNodeWithinDoc.AppendChild(node);
This code results in-
<SomeElement name="foo" xmlns="">
<SubElement name="bar" />
</SomeElement>
in the final document.
I use a different construct when I do not have to go from a string to XML-
XmlElement elem = doc.CreateElement("SomeElement", "http://www.omg.org/space/xtce");
elem.SetAttribute("name","foo");
someXmlNodeWithinDoc.AppendChild(elem);
and this yields exactly what I want.
<SomeElement name="foo">
</SomeElement>
I would like to do something line this in my current solution
node.setNamespace("http://www.omg.org/space/xtce") then the document would omit xmlns because it is same as root.
Can someone tell me the idiomatic way to build a document with a single namespace use within, where some elements are stored in the model as a string?
This issue is almost identical to mine except the solution has the luxury of only providing the sub element as a string (everything under "new"). I need the entire element.
string xmlRoot = "<Root xmlns=\"http://www.omg.org/space/xtce\"></Root>";
string xmlChild = "<SomeElement name=\"foo\"><SubElement name = \"bar\"/></SomeElement >";
XDocument xDoc = XDocument.Parse(xmlRoot);
XDocument xChild = XDocument.Parse(xmlChild);
xChild.Root.Name = xDoc.Root.GetDefaultNamespace() + xChild.Root.Name.LocalName;
foreach (XElement xChild2 in xChild.Root.Nodes())
{
xChild2.Name = xDoc.Root.GetDefaultNamespace() + xChild2.Name.LocalName;
}
xDoc.Root.Add(xChild.Root);
string xmlFinal = xDoc.ToString();
This is the solution I ended up with. I did not use #shop350 solution because I didn't want to use XDocument,XElement... Thank you for the feedback though!
// create a fragment which I am going to build my element based on text.
XmlDocumentFragment frag = doc.CreateDocumentFragment();
// here I wrap my desired element in another element "dc" for don't care that has the namespace declaration.
string str = "";
str = "<dc xmlns=\"" + xtceNamespace + "\" ><Parameter name=\"paramA\" parameterTypeRef=\"paramAType\"><AliasSet><Alias nameSpace=\"ID\" alias=\"0001\"/></AliasSet></Parameter></dc>";
// set the xml for the fragment (same namespace as doc)
frag.InnerXml = str;
// let someXmlNodeWithinDoc be of type XmlNode which I determined based on XPath search.
// Here I attach the child element "Parameter" to the XmlNode directly effectively dropping the element <dc>
someXmlNodeWithinDoc.AppendChild(frag.FirstChild.FirstChild);
How to get the xml node value in a string.
i am getting This error
Data at the root level is invalid. Line 1, position 1.
error shown in this line
xmldoc.LoadXml(xmlFile);
my xml
<?xml version="1.0" encoding="utf-8" ?>
<UOM>
<!-- The selected currency used will be stored here for Code reference" -->
<ActiveCurrencyType>
<ActiveCurrency>U.S.Dollar</ActiveCurrency>
<ActiveCode>USD</ActiveCode>
<ActiveSymbol>$</ActiveSymbol>
</ActiveCurrencyType>
<!-- The selected Dimension used will be stored here for Code reference -->
<ActiveDimension>
<ActiveDimensionUOM>Inches</ActiveDimensionUOM>
<ActiveDimensionSymbol>.in</ActiveDimensionSymbol>
</ActiveDimension>
<!-- The selected weight used will be stored here for Code reference -->
<ActiveWeight>
<ActiveWeightUOM>Pounds</ActiveWeightUOM>
<ActiveWeightSymbol>lb</ActiveWeightSymbol>
</ActiveWeight>
</UOM>
C# code
string xmlFile = Server.MapPath("~/HCConfig/HCUOM.xml");
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(xmlFile);
XmlNodeList nodeList = xmldoc.GetElementsByTagName("ActiveDimensionSymbol");
string ActiveDimensionSymbol = string.Empty;
foreach (XmlNode node in nodeList)
{
ActiveDimensionSymbol = node.InnerText;
}
How can I achieve this?
You're using the wrong overload, LoadXml doesn't do what you think it does.
Use xmldoc.Load(xmFile); because that method takes an file path as input. LoadXml expects an string with xml in it.
The exception is an indicator of that mistake. What is processed is not XML, and a filepath isn't that.
After this changes the string ActiveDimensionSymbol contains .in if I run this locally.
If you want to use LoadXml you should first read your whole file in a string, for example like so:
xmldoc.LoadXml(File.ReadAllText(xmlFile));
but is really only overhead to call File.ReadAllText if there is an method that accepts a file.
You can use the Descendants() method to get all XElements by certain name, found in the System.Xml.Linq namespace.
XDocument doc = XDocument.Load("XMLFile1.xml");
string[] allActiveWeightUOMs = doc.Descendants("ActiveWeightUOM").Select(o => o.Value).ToArray();
// allActiveWeightUOMs : "Pounds" ...
As can seen here link the method that you are using to load the XML excepts xml by string not xml file. You can use XmlDocument.Load instead of XmlDocument.LoadXml
Try this code its works just fine with this xml
string xmlFile = Server.MapPath("~/HCConfig/HCUOM.xml");
XDocument doc = XDocument.Load(xmlFile );
var nodeList = doc.Descendants("ActiveDimensionSymbol");
string ActiveDimensionSymbol = string.Empty;
foreach (var node in nodeList)
{
ActiveDimensionSymbol = node.Value;
}
I have been trying to extract one value from a XML file, and then store it on the same file but in another node, I tried all the examples i've found on the net, read XPath Syntax documentation like hell and still can't get it to work.
I must take the <Documento ID="F60T33"> ID Value (which may vary) and copy it into <Reference URI="#F60T33">.
But I can't even do that if I can't manage to parse the lines, most of times node/variables/"", or I get an "object reference not established as object instance error".
Here's the code:
// Create a new XML document.
XmlDocument xmlDoc = new XmlDocument();
// Load an XML file into the XmlDocument object.
xmlDoc.PreserveWhitespace = true;
xmlDoc.Load(pfile);
//TEST !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PROBLEMA
XmlNodeList Documentos = xmlDoc.GetElementsByTagName("//Documento");
XmlNodeList DatosDocumento = ((XmlElement)Documentos[0]).GetElementsByTagName("ID");
foreach (XmlElement nodo in DatosDocumento)
{
int I = 0;
XmlNodeList ID = nodo.GetElementsByTagName("ID");
Console.WriteLine("Elemento nombre ... {0}}", ID[i].InnerText);
}
//
XmlNodeList nodes = xmlDoc.SelectNodes("EnvioDTE");
XmlNode nodesimple = xmlDoc.SelectSingleNode("EnvioDTE");
Console.WriteLine("Lista Nodos: " + nodes.Count);
Console.WriteLine("Nodo Simple: " + nodesimple.InnerText);
foreach (XmlNode node in nodes)
{
string id = node.Attributes["ID"].InnerText;
Console.WriteLine(id);
}
I am almost certain the problem is on the XPath Syntax, but I can't get it to work.
Sadly I can't use XDocument as im using .NET 3.5 for this task, I would really appreciate some help on this, by behand apologize my bad english
As the XML file is too big, I'll put it here on this URL
http://puu.sh/bVNDc/31e4da5a26.xml
If you can get your references right for using System.Linq.XDocument you can do:
string idValue = xDocument.XPathSelectElement("//EnvioDTE/SetDTE")
.Attributes().SingleOrDefault(a => a.Name == "ID").Value;
The xml is coming from a url and all I need is the pull the string "N0014E1" from it. I am not sure why this code is not working. I put a try block around it and I get a "Data root level is invalid"
xml:
<obj is="c2g:Network " xsi:schemaLocation="http://obix.org/ns/schema/1.0/obi/xsd" href="http://192.168.2.230/obix/config/">
<ref name="N0014E1" is="c2g:LOCAL c2g:Node"xsi:schemaLocation="http://obix.org/ns/sc/1.0/obix/xsd" href="N0014E1/"></ref>
</obj>
C# code:
public static string NodePath = "http://" + MainClass.IpAddress + ObixPath;
public static void XMLData()
{
XmlDocument NodeValue = new XmlDocument();
NodeValue.LoadXml(NodePath);
var nodes = NodeValue.SelectNodes(NodePath);
foreach (XmlNode Node in nodes)
{
HttpContext.Current.Response.Write(Node.SelectSingleNode("//ref name").Value);
Console.WriteLine(Node.Value);
}
//Console.WriteLine(Node);
Console.ReadLine();
}
Your SelectNodes and SelectSingleNode commands are incorrect. Both expect an xpath string to identify the node.
Try the following
string xml = #"<obj is=""c2g:Network "" href=""http://192.168.2.230/obix/config/""><ref name=""N0014E1"" is=""c2g:LOCAL c2g:Node"" href=""N0014E1/""></ref></obj>";
XmlDocument NodeValue = new XmlDocument();
NodeValue.LoadXml(xml);
XmlNode r = NodeValue.SelectSingleNode("//ref[#name]");
if (r != null)
{
System.Diagnostics.Debug.WriteLine(r.Attributes["name"].Value);
}
Also, Note, that LoadXml method simply loads an xml string; it will not load from a remote url.
As #kevintdiy has pointed out your xml is not entirely correct. In the sample above I have stripped out the xsi reference as you are lacking a definition for it.
If you have access to the source xml, either remove the reference to xsi if its not required or add a definition for it to the root node.
If this is not possible, then you may want to consider using regular expression or other string based methods for getting the value.