Xml Root.add value with Special Character( :) - c#

I have an XML file
which is
<?xml version="1.0" encoding="utf-8"?>
<urlset >
</urlset>
I'm trying to add an XElement with special characters (:) code behind
string xmlpath = #"~/myxml.xml";
string path = Server.MapPath(xmlpath);
string title="SomeString"
XDocument doc = XDocument.Load(path);
XElement root = new XElement("url");
root.Add(new XElement("Video:title", "title"));//here is the problem i have Special char (:) which not allowed
doc.Element("urlset").Add(root);
also i can't use &qoute; becuse it's contniue special char & Please i need help if any one can help i would be thankful thanks a lot for your time guys and thank a lot for giving time to read my queation

I'm trying to add an XElement with special characters (:) code behind
Try using a XmlDocument which will allow creating an XmlElement with specified name and namespace.
string xmlpath = #"~/myxml.xml";
string path = Server.MapPath(xmlpath);
XmlDocument doc = new XmlDocument();
doc.Load(path);
var mainRoot = doc.DocumentElement; //urlset element
var urlRoot = doc.CreateElement("url"); //create url element
urlRoot.AppendChild(doc.CreateElement("Video:title","title")); //add element to the url element
mainRoot.AppendChild(urlRoot); // add this new element to the main root of urlset
Example Output:
<?xml version="1.0" encoding="utf-8"?>
<urlset>
<url>
<Video:title xmlns:Video="title" />
</url>
</urlset>
Or if you just want a Video node with namespace of title...
urlRoot.AppendChild(doc.CreateElement("Video","title"));
The output of this above:
<?xml version="1.0" encoding="utf-8"?>
<urlset>
<url>
<Video xmlns="title"/>
</url>
</urlset>
Please let me know if this isn't your expected output.

Related

Accessing the xml tag with C# and updating the content

I have an xml file that I converted from pdf to xml.
Example XML looks as follows
<?xml version="1.0" encoding="UTF-8"?>
<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.graphics">
<office:body>
<office:drawing>
<draw:page draw:name="page1" draw:style-name="dp2" draw:master-page-name="master-page3">
<draw:frame draw:style-name="gr9" draw:text-style-name="P10" draw:layer="layout" svg:width="1.242cm" svg:height="0.357cm" svg:x="17.055cm" svg:y="11.787cm">
<draw:text-box>
<text:p text:style-name="P2"><text:span text:style-name="T6">Example</text:span></text:p>
</draw:text-box>
</draw:frame>
</draw:page>
</office:drawing>
</office:body>
</office:document>
The C# code I'm trying to use:
XmlDocument doc = new XmlDocument();
XmlNamespaceManager namespaces = new XmlNamespaceManager(doc.NameTable);
namespaces.AddNamespace("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0");
doc.Load("invoiceto.xml");
doc.SelectSingleNode("/draw:frame/draw:text-box/text:p/text:span", namespaces).InnerText = "new value";
I get this error
'' text 'namespace prefix not defined.'
I want to replace the text of example with C# but how can I get to the <text: span text: style-name = "T6"> tag with C#?
First of all the prefix added to XmlNamespaceManager shouldn't include the xmlns part. Then you also need to add the prefix text besides draw because both will be used in the XPath expression for calling SelectSingleNode. Last, since the element <draw:frame> isn't the root element you need to either specify full path starting from the root or start the XPath using // (the descendant-or-self axis) instead:
XmlNamespaceManager namespaces = new XmlNamespaceManager(doc.NameTable);
namespaces.AddNamespace("draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0");
namespaces.AddNamespace("text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0");
doc.SelectSingleNode("//draw:frame/draw:text-box/text:p/text:span", namespaces).InnerText = "new value";
dotnetfiddle demo

I can not add a node to the XML file within the right element

When I save a new Question element, I need it to be inside the questions element, which in turn is inside the QuestionCollection, but the way I'm saving the new elements are outside the questions and are not read later.
How XML is getting: (ABA IS NEW ELEMENT)
<?xml version="1.0" encoding="UTF-8"?>
<QuestionCollection>
<Question Titulo="ABA">
<Enunciado>ABB</Enunciado>
<Resposta1>ABC</Resposta1>
<Resposta2>ABD</Resposta2>
<Resposta3>ABE</Resposta3>
<Resposta4>ABF</Resposta4>
<RespostaC>ABC</RespostaC>
</Question>
<Questions>
<START>
</START>
<Question Titulo="AAA">
<Enunciado>AAB</Enunciado>
<Resposta1>AAC</Resposta1>
<Resposta2>AAD</Resposta2>
<Resposta3>AAE</Resposta3>
<Resposta4>AAF</Resposta4>
<RespostaC>AAF</RespostaC>
</Question>
</Questions>
</QuestionCollection>
How should I stay:
<?xml version="1.0" encoding="UTF-8"?>
<QuestionCollection>
<Questions>
<START>
</START>
<Question Titulo="AAA">
<Enunciado>AAB</Enunciado>
<Resposta1>AAC</Resposta1>
<Resposta2>AAD</Resposta2>
<Resposta3>AAE</Resposta3>
<Resposta4>AAF</Resposta4>
<RespostaC>AAF</RespostaC>
</Question>
<Question Titulo="ABA">
<Enunciado>ABB</Enunciado>
<Resposta1>ABC</Resposta1>
<Resposta2>ABD</Resposta2>
<Resposta3>ABE</Resposta3>
<Resposta4>ABF</Resposta4>
<RespostaC>ABC</RespostaC>
</Question>
</Questions>
</QuestionCollection>
Part of Code
XmlDocument doc = new XmlDocument ();
doc.Load ("Assets/Resources/Questions.xml");
XmlNode root = doc.DocumentElement;
XmlElement q = doc.CreateElement ("Question");
q.InnerText = Question;
XmlNode qa = doc.SelectSingleNode ("QuestionCollection/Questions/START");
root.InsertAfter(q,qa);
doc.Save ("Assets/Resources/Questions.xml");
Instance.CloseWindow ();
ERROR: ArgumentException: The reference node is not a child of this node.
#Marshall Tigerus is correct, but there's more;
Change this:
XmlElement q = doc.CreateElement("Question");
q.InnerText = Question;
XmlNode qa = doc.SelectSingleNode("QuestionCollection/Questions");
XmlNode start = qa.SelectSingleNode("START");
qa.InsertAfter(q,start);
Assuming you haven't put a typo in your code above, I think I know what is happening.
Your XML structure has QuestionCollection as an element, while your SelectSingleNode call has QuestionsCollection. This will cause the qa node to be null.
The InsertAfter method has logic in it that will handle the reference node being null. It will instead insert the new element as a child of the root element at the beginning of the list (https://msdn.microsoft.com/en-us/library/system.xml.xmlnode.insertafter(v=vs.110).aspx)
This appears to be what is happening here. Remove that extra s from your SelectSingleNode parameters and you should be good.

Unable to use XmlDocument.SelectSingleNode on XML with Two Namespaces

I'm trying to parse the following XML:
<?xml version="1.0" encoding="utf-8"?>
<A2AAnf:MPPPPPP xsi:schemaLocation="urn:A2AAnf:xsd:$MPPPPPP.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:A2AAnf="urn:A2AAnf:xsd:$MPPPPPP">
<A2AAnf:Num>0</A2AAnf:Num>
<A2AAnf:FIT xmlns="urn:iso:std:iso:20022:xsd:003.001">
<Hdr>
<Inf>
<Mtd>TEST</Mtd>
</Inf>
</Hdr>
</A2AAnf:FIT>
I want to access the <Mtd> tag.
XMLQuire shows the path to be /A2AAnf:MPPPPPP/A2AAnf:FIT/dft:Hdr/dft:Inf/dft:Mtd, but when I'm trying to parse it using the following code:
XmlDocument xmldocument = new XmlDocument();
var xmlNameSpaceManager = new XmlNamespaceManager(xmldocument.NameTable);
xmlNameSpaceManager.AddNamespace("A2AAnf", "urn:A2AAnf:xsd:$MPPPPPP");
try
{
xmldocument.LoadXml(m_XML);
var node = xmldocument.SelectSingleNode("/A2AAnf:MPPPPPP/A2AAnf:FIT/dft:Hdr/dft:Inf/dft:Mtd", xmlNameSpaceManager);
}
I receive the following error:
namespace prefix 'dft' is not defined
And since I can't find "dft" in my XML, I also tried to remove the "dft" prefix and search for the same string without "dft". This time, nothing was returned.
What am I missing?
You have to add dft to your XmlNamespaceManager:
var xmlNameSpaceManager = new XmlNamespaceManager(xmldocument.NameTable);
xmlNameSpaceManager.AddNamespace("A2AAnf", "urn:A2AAnf:xsd:$MPPPPPP");
xmlNameSpaceManager.AddNamespace("dft", "urn:iso:std:iso:20022:xsd:003.001");
The prefixes you use in your XPath query have nothing to do with the prefixes used in the XML document. They are instead the prefixes you define in your XmlNamespaceManager.

How can I add xml attributes with different prefixes/namespaces in C#?

I need to be able to create an XML Document that looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rootprefix:rootname
noPrefix="attribute with no prefix"
firstprefix:attrOne="first atrribute"
secondprefix:attrTwo="second atrribute with different prefix">
...other elements...
</rootprefix:rootname>
Here's my code:
XmlDocument doc = new XmlDocument();
XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", "UTF-8", "yes");
doc.AppendChild(declaration);
XmlElement root = doc.CreateElement("rootprefix:rootname", nameSpaceURL);
root.SetAttribute("schemaVersion", "1.0");
root.SetAttribute("firstprefix:attrOne", "first attribute");
root.SetAttribute("secondprefix:attrTwo", "second attribute with different prefix");
doc.AppendChild(root);
Unfortunately, what I'm getting for the second attribute with the second prefix is no prefix at all. It's just "attrTwo"--like the schemaVersion attribute.
So, is there a way to have different prefixes for attributes in the root element in C#?
This is just a guide for you. May be you can do:
NameTable nt = new NameTable();
nt.Add("key");
XmlNamespaceManager ns = new XmlNamespaceManager(nt);
ns.AddNamespace("firstprefix", "fp");
ns.AddNamespace("secondprefix", "sp");
root.SetAttribute("attrOne", ns.LookupPrefix("fp"), "first attribute");
root.SetAttribute("attrTwo", ns.LookupPrefix("sp"), "second attribute with different prefix");
This will result in:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rootprefix:rootname schemaVersion="1.0" d1p1:attrOne="first attribute" d1p2:attrTwo="second attribute with different prefix" xmlns:d1p2="secondprefix" xmlns:d1p1="firstprefix" xmlns:rootprefix="ns" />
Hope this will be of any help!
I saw a post on another question that ended up solving the issue. I basically just created a string that had all the xml in it, then used the LoadXml method on an instance of XmlDocument.
string rootNodeXmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ "<rootprefix:rootname schemaVersion=\"1.0\" d1p1:attrOne=\"first attribute\""
+ "d1p2:attrTwo=\"second attribute with different prefix\" xmlns:d1p2=\"secondprefix\""
+ "xmlns:d1p1=\"firstprefix\" xmlns:rootprefix=\"ns\" />";
doc.LoadXml(rootNodeXmlString);

How to correctly parse an XML document with arbitrary namespaces

I am trying to parse somewhat standard XML documents that use a schema called MARCXML from various sources.
Here are the first few lines of an example XML file that needs to be handled...
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd">
<marc:record>
<marc:leader>00925njm 22002777a 4500</marc:leader>
and one without namespace prefixes...
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
<record>
<leader>01142cam 2200301 a 4500</leader>
Key point: in order to get the XPaths to resolve further along in the program I have to go through a regex routine to add the namespaces to the NameTable (which doesn't add them by default). This seems unnecessary to me.
Regex xmlNamespace = new Regex("xmlns:(?<PREFIX>[^=]+)=\"(?<URI>[^\"]+)\"", RegexOptions.Compiled);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlRecord);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);
MatchCollection namespaces = xmlNamespace.Matches(xmlRecord);
foreach (Match n in namespaces)
{
nsMgr.AddNamespace(n.Groups["PREFIX"].ToString(), n.Groups["URI"].ToString());
}
The XPath call looks something like this...
XmlNode leaderNode = xmlDoc.SelectSingleNode(".//" + LeaderNode, nsMgr);
Where LeaderNode is a configurable value and would equal "marc:leader" in the first example and "leader" in the second example.
Is there a better, more efficient way to do this? Note: suggestions for solving this using LINQ are welcome, but I would mainly like to know how to solve this using XmlDocument.
EDIT: I took GrayWizardx's advice and now have the following code...
if (LeaderNode.Contains(":"))
{
string prefix = LeaderNode.Substring(0, LeaderNode.IndexOf(':'));
XmlNode root = xmlDoc.FirstChild;
string nameSpace = root.GetNamespaceOfPrefix(prefix);
nsMgr.AddNamespace(prefix, nameSpace);
}
Now there's no more dependency on Regex!
If you know there is going to be a given element in the document (for instance the root element) you could try using GetNamespaceOfPrefix.

Categories

Resources