Modify a xml node with spacing and quotes as attricutes - c#

I am trying to access to the child node of an XML but the my first XML node has spacing and quotes as attributes.
var xml = #"<Envelope xsd "http">
<Catalog>
<Price>
<Value Default ="yes">P1</Value>
</Price>
</Catalog>
</Envelope>";
Im trying to change the attribute value of Default from "yes" to "1" but node always returns null.
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
var node = doc.SelectSingleNode("/*/Catalog/Price/Value");
Any ideas?

I do not think that is valid xml, did you perhaps mean the following
using System;
using System.Globalization;
using System.Xml;
namespace ConsoleApplication9
{
class Program
{
private static void Main(string[] args)
{
//Valid XML
string xml = #"<Envelope xsd='http'>
<Catalog>
<Price>
<Value Default='yes'>P1</Value>
</Price>
</Catalog>
</Envelope>";
var doc = new XmlDocument();
doc.LoadXml(xml);
//Select the Value Node
XmlNode node = doc.SelectSingleNode("/*/Catalog/Price/Value");
//Set the Default attribute to 1
node.Attributes["Default"].Value = 1.ToString(CultureInfo.InvariantCulture);
//Check the output
Console.WriteLine(doc.InnerXml.ToString(CultureInfo.InvariantCulture));
//Press enter to exit
Console.ReadLine();
}
}
}
Just saying.

See http://msdn.microsoft.com/en-us/library/ms256086(v=vs.110).aspx.
Use // instead of /* since // gets the root of the document

This might appear a little hardcoded but it should work:
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
Namespace ns= "http"; //set the namespace of the root node here
//the following is where you change the value to 1
doc.Document.Descendants(ns+"Envelope").FirstorDefault().Descendants(ns+"Catalog").Descendants(ns+"Price").FirstorDefault().Elements("Value").Attribute("Default").SetValue("1");
Also, the xml looks a little wrong to me, as someone mentioned, the root node needs to be corrected.

Related

Reading a XML File using XPath Expression in C#

I am currently having a problem with reading a XML file using XPath expression. I have used the XmlDocument class. When I try reading a particular node from the XML, I get an empty list. The node which I am trying to read is the ID below ProductionRequest.
Here is the XML file which I tried to read:
<?xml version="1.0" encoding="iso-8859-1"?>
<ProductionSchedule xmlns="http://www.wbf.org/xml/b2mml-v02">
<ID>00000020000000</ID>
<Location>
<EquipmentID>8283</EquipmentID>
<EquipmentElementLevel>Site</EquipmentElementLevel>
<Location>
<EquipmentID>0</EquipmentID>
<EquipmentElementLevel>Area</EquipmentElementLevel>
</Location>
</Location>
<ProductionRequest>
<ID>0009300000000</ID>
<ProductProductionRuleID>W001</ProductProductionRuleID>
<StartTime>2017-04-20T23:57:20</StartTime>
<EndTime>2017-04-20T24:00:00</EndTime>
</ProductionRequest>
</ProductionSchedule>
This is the code which I used to read the above XML
using System;
using System.Xml.Linq;
using System.Xml;
using System.Xml.XPath;
namespace XML
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
string fullName = "F:\\Programming\\XML\\Example XML.xml";
XmlDocument xreader = new XmlDocument();
xreader.Load(fullName);
XmlNode root = xreader.DocumentElement;
XmlNodeList xnList1 =
xreader.SelectNodes("/ProductionSchedule/ProductionRequest/ID");
}
}
}
I could not find the cause for this problem. Could anyone help me in this regard. Looking forward for valuable inputs.
Your xml contains namespace http://www.wbf.org/xml/b2mml-v02 at root level node <ProductionSchedule>
And you are using the XPath expression /ProductionSchedule/ProductionRequest/ID but this XPath expression is not suitable for this xml document and that's why you can't get any desired value.
You need to use the below XPath expression to get the id's of all <ProductionRequest> node.
XmlNodeList xnList1 = xreader.SelectNodes("//*[name()='ProductionSchedule']/*[name()='ProductionRequest']/*[name()='ID']");
OR you can add namespace manually like
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xreader.NameTable);
nsmgr.AddNamespace("x", "http://www.wbf.org/xml/b2mml-v02");
XmlNodeList xnList1 = xreader.SelectNodes("//x:ProductionSchedule/x:ProductionRequest/x:ID", nsmgr);
And finally, you can read id from any of the parent nodes in variable xnList1 like
foreach (XmlNode id in xnList1)
{
Console.WriteLine(id.InnerText);
}
Output:

How do I read Element in specific XML file in C#?

my file XML:
<document xmlns="http://www.abbyy.com/FineReader_xml/FineReader10-schema-v1.xml" version="1.0" producer="ABBYY FineReader Engine 11" languages="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.abbyy.com/FineReader_xml/FineReader10-schema-v1.xml http://www.abbyy.com/FineReader_xml/FineReader10-schema-v1.xml">
<page width="1006" height="636" resolution="300" originalCoords="1" rotation="RotatedUpsidedown">
<block blockType="Text" blockName="" l="979" t="613" r="1006" b="636"><region><rect l="979" t="613" r="1006" b="636"/></region>
<text>
<par lineSpacing="890">
<line baseline="17" l="985" t="620" r="1006" b="636"><formatting lang="EnglishUnitedStates"><charParams l="985" t="620" r="1006" b="636" suspicious="1">r</charParams></formatting></line></par>
</text>
</block>
<block blockType="Barcode" blockName="" l="242" t="21" r="772" b="116"><region><rect l="242" t="21" r="772" b="116"/></region>
<text>
<par><line baseline="0" l="0" t="0" r="0" b="0"><formatting lang="">049102580225180310</formatting></line></par>
</text>
<barcodeInfo type="INTERLEAVED25"/>
</block>
</page>
</document>
I want extract number 049102580225180310 located in <formatting>..</formatting>
I try this code:
XElement racine = XElement.Load("test_XML.xml");
var query = from xx in racine.Elements(XName.Get("block"))
select new
{
CodeBar= xx.Attribute(XName.Get("formatting")).Value
};
But I haven't nothing
Here's a console program, that gets the 2nd formatting (where lang='') node.
using System;
using System.Xml;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
XmlDocument xml = new XmlDocument();
xml.Load("c:\\temp\\test.xml");
NameTable nt = new NameTable();
XmlNamespaceManager nsmgr;
nsmgr = new XmlNamespaceManager(nt);
nsmgr.AddNamespace("html", xml.DocumentElement.NamespaceURI);
XmlNode ndFormat = xml.SelectSingleNode("//html:formatting[#lang='']", nsmgr);
if (ndFormat != null) {
Console.WriteLine(ndFormat.InnerText);
}
}
}
}
You have a couple issues here:
Your XML has a default namespace in the root node:
<document xmlns="http://www.abbyy.com/FineReader_xml/FineReader10-schema-v1.xml" version="1.0"
Thus all child elements are in this namespace, and so when querying for elements by their Name the appropriate namespace must be used when constructing an XName for which to search.
The <formatting> nodes are not direct children of the <block> nodes, they are nested within several levels of XML. Also, they are XML elements, not XML attributes.
Similarly the <block> elements are not direct children of the <document> root element, they are nested inside a <page> element.
In such cases XElement.Descendants(name) can be used to find nested elements by name.
Thus your query should be:
var ns = racine.Name.Namespace; // The root default namespace used by all the elements in the XML.
var query = from block in racine.Descendants(ns + "block")
from formatting in block.Descendants(ns + "formatting")
select new
{
CodeBar= (string)formatting,
};
Sample fiddle that outputs the values of the two <formatting> elements:
{ CodeBar = r }
{ CodeBar = 049102580225180310 }

Reading XML file results in index out of range exception

Using C# I have an XML file like
<?xml version="1.0" encoding="utf-8"?>
<root>
<Account>
<name>Jani</name>
</Account>
</root>
and I also have a function to read the name node as:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("lib//user.xml");
XmlNode node;
node = xmlDoc.DocumentElement;
string name = node.Attributes[0].Value;
label1.Text = name.ToString();
but I am getting index out of range error as:
Why is this happening?
node = xmlDoc.DocumentElement;
string name = node.Attributes[0].Value;
node is your root node. Which looks like this:
<root>
How many attributes does it have? None, as it turns out. An attribute in XML is one of these bar="baz" things:
<foo bar="baz">
node.Attributes[0] refers to the first attribute. There is no first attribute, there's no second attribute -- you didn't use attributes in this XML at all. Hence, that's out of range. There's no first item in an empty collection.
What you want is an element named name, which is farther down inside your XML tree.
Probably this:
var node = xmlDoc.DocumentElement.SelectSingleNode("/root/Account/name");
And then you'll want to look at node.InnerText to get "Jani" out of it.
You are trying to read node.Attributes[0].Value but there is no attribtues in your sample XML file. Not sure of the exact syntax but it should probably be closer to node.Value
As mentioned by other answers, your current XML does not have attributes.
private void DoIt()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"M:\StackOverflowQuestionsAndAnswers\38924171\38924171\data.xml");
XmlNode node;
node = xmlDoc.DocumentElement;
//string name = node.Attributes[0].Value;
string name = node["Account"].InnerText;
}
If your XML did have attributes
<?xml version="1.0" encoding="utf-8"?>
<root>
<Account name="Jani" />
</root>
Then you could do this:
private void DoItAgain()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"M:\StackOverflowQuestionsAndAnswers\38924171\38924171\data2.xml");
XmlNode node;
node = xmlDoc.DocumentElement;
string name = node["Account"].Attributes[0].Value;
}

Finding Correct Xpath C# [duplicate]

I'm having this XML document with namespaces and I want to extract some nodes using XPath.
Here's the document:
<ArrayOfAnyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
<anyType xsi:type="Document">
<Id>5</Id>
<Title>T1</Title>
</anyType>
<anyType xsi:type="Document">
<Id>15</Id>
<Title>T15</Title>
</anyType>
</ArrayOfAnyType>
What's the XPath expression going to be if I want to extract all "anyType" elements with xsi:type="Document"?
I've tried this:
//anyType[#xsi:type="Document"]
and it doesn't work:
If you are using C# then you need to specify the namespace for the "anyType" element in your XPath:
var xml = new XmlDocument();
xml.LoadXml( "your xml" );
var names = new XmlNamespaceManager( xml.NameTable );
names.AddNamespace( "xsi", "http://www.w3.org/2001/XMLSchema-instance" );
names.AddNamespace( "a", "http://tempuri.org/" );
var nodes = xml.SelectNodes( "//a:anyType[#xsi:type='Document']", names );
I think that
//anyType[namespace-uri() = "http://www.w3.org/2001/XMLSchema-instance"][local-name() = "type"]
Will do what you want.
This way you don't need to specify namespace:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml("your xml");
XmlNode node = xmlDoc.SelectSingleNode("/*[local-name() = 'anyType']");
XmlNode nodeToImport = xmlDoc2.ImportNode(node, true);
xmlDoc2.AppendChild(nodeToImport);
Had nearly the same problem, I forgot to add the correct namespace for xsi:type
(http://www.w3.org/2001/XMLSchema-instance) was using http://www.w3.org/2001/XMLSchema
and I did never get any result - now it is working the following way:
<xsl:value-of select="/item1/item2/item3/#xsi:type"></xsl:value-of>

How to add attributes to xml using XmlDocument in c# .net CF 3.5

I need to create an attribute "abc" with the prefix "xx" for an element "aaa". The following code adds the prefix but it also adds the namespaceUri to the element.
Required Output:
<mybody>
<aaa xx:abc="ddd"/>
<mybody/>
My Code:
XmlNode node = doc.SelectSingleNode("//mybody");
XmlElement ele = doc.CreateElement("aaa");
XmlAttribute newAttribute = doc.CreateAttribute("xx","abc",namespace);
newAttribute.Value = "ddd";
ele.Attributes.Append(newAttribute);
node.InsertBefore(ele, node.LastChild);
The above code generates :
<mybody>
<aaa xx:abc="ddd" xmlns:xx="http://www.w3.org/1999/XSL/Transform"/>
<mybody/>
Desired output is
<mybody>
<aaa xx:abc="ddd"/>
<mybody/>
And the declaration of the "xx" attribute should be done in the root node like :
<ns:somexml xx:xsi="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://x.y.z.com/Protocol/v1.0">
How can if get the output in the deisred format? If the xml is not in this desired format then it cannot be processed anymore..
Can anyone help?
Thanks,
Vicky
I believe it's just a matter of setting the relevant attribute directly on the root node. Here's a sample program:
using System;
using System.Globalization;
using System.Xml;
class Test
{
static void Main()
{
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("root");
string ns = "http://sample/namespace";
XmlAttribute nsAttribute = doc.CreateAttribute("xmlns", "xx",
"http://www.w3.org/2000/xmlns/");
nsAttribute.Value = ns;
root.Attributes.Append(nsAttribute);
doc.AppendChild(root);
XmlElement child = doc.CreateElement("child");
root.AppendChild(child);
XmlAttribute newAttribute = doc.CreateAttribute("xx","abc", ns);
newAttribute.Value = "ddd";
child.Attributes.Append(newAttribute);
doc.Save(Console.Out);
}
}
Output:
<?xml version="1.0" encoding="ibm850"?>
<root xmlns:xx="http://sample/namespace">
<child xx:abc="ddd" />
</root>

Categories