XAttribute generates bogus prefix - c#

I am trying to generate a piece of xml data using linq to xml.
XNamespace xsins = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
XAttribute xsiniltrue = new XAttribute(xsins+"Exists", "true");
XElement elem = new XElement("CustomerRecord", xsiniltrue);
This generates the prefix for xsins at runtime and they looks bogus.
<Fragment>
<CustomerRecord p5:Exists="true" xmlns:p5="w3.org/2001/XMLSchema-instance"; />
</Fragment>
<Fragment>
<CustomerRecord p3:Exists="false" xmlns:p3="w3.org/2001/XMLSchema-instance"; />
</Fragment>
to be merged as
<Fragment xmlns:p5="w3.org/2001/XMLSchema-instance"; >
<CustomerRecord p5:Exists="true" />
<CustomerRecord p5:Exists="false" />
</Fragment>
Also tried to use XMLWriter,
XNamespace xsins = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
using (var writer = XmlWriter.Create(fullPath, settings))
{
writer.WriteStartDocument(true);
writer.WriteStartElement(string.Empty, "Company", "urn:schemas-company");
//writer.WriteAttributeString(xsins.GetName("xsi"), "http://www.w3.org/2001/XMLSchema-instance");
writer.WriteStartElement(string.Empty, "Add", "urn:schemas-company");
foreach (var qx in resultXMLs)
{
qx.WriteTo(writer);
}
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
}
I have finally cracked it (atleast I hope), below piece solved my issue
using (var writer = XmlWriter.Create(fullPath, settings))
{
writer.WriteStartDocument(true);
writer.WriteStartElement(string.Empty, "Company", "urn:schemas-company");
writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
writer.WriteStartElement(string.Empty, "Add", "urn:schemas-company");
foreach (var qx in fragments)
{
qx.SetAttributeValue(XNamespace.Xmlns + "xsi", xsins.ToString());
qx.WriteTo(writer);
}
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
}

You want to control the XML prefix outputted. For reference an MSDN site
Basically you just need to add the xml:xsi to your root node and Linq to XML should take care of the rest.
Note that when you get into really complex examples it tends to fall apart, but it should work in this case.
EDIT:
To remove extraneous attributes, you could simply do it by hand:
foreach(var element in root.Descendents())
{
foreach (var attribute in element.Attributes())
{
if (attribute.Name.Namespace == XNamespace.Xmlns)
attribute.Remove();
}
}
Note the above is rough, I don't have an XML project handy.
EDIT:
I am not sure what your input is, but here is an example of hard coding your expected output:
var xsi = XNamespace.Get("http://www.w3.org/2001/XMLSchema-instance");
var fragment =
new XElement("Fragment",
new XAttribute(XNamespace.Xmlns + "p5", xsi.ToString()),
new XElement("CustomerRecord",
new XAttribute(xsi + "Exists", "true")),
new XElement("CustomerRecord",
new XAttribute(xsi + "Exists", "false")));
I tested this and it outputs identical to what you asked for (well I tested in F#, so sorry if there is a syntax error)

Related

XElement XML ToString malformed [ ]

So I m parsing some xml. I create my XElement and run the ToString() method. I look at the results and they are all wrong.
<root>[elementName, ElementValue ]</root>
When It should look like
<root>
<data name="Name">
<value>Value</value>
</data>
</root>
This is really weird. I've used XML plenty of times and have never run into this. I have looked on the web and I can't find anything. When I step through the XDocument creation process the ToString() for each element is correct. What is going on? How can I troubleshoot this?
Here is my code
string WriteXml(Dictionary<string, string> dic)
{
var root = new XElement("root");
foreach (var pair in dic)
{
var element = new XElement("data", pair.Value);
element.Add(new XAttribute("name", pair.Key));
root.Add(pair);
}
var doc = new XDocument(new XDeclaration("1.0", "utf-8", null), root);
var s = doc.ToString();
Console.WriteLine(s);
return doc.ToString();
}

XmlDocument from XML string that contains custom namespaces causes XmlException?

I need to create an XmlDocument partly by using old XML and partly by creating new. The problem is that the old XML contains custom namespaces and I can't seem to be able to use them as I get an XmlException. I've tried to add the namespace to many different places but I can't get over the Exception!
The Exception
System.Xml.XmlException was unhandled by user code
Message='my' is an undeclared prefix. Line 1, position 42.
Source=System.Xml
My Code
XmlDocument doc = new XmlDocument();
XmlSchema schema = new XmlSchema();
schema.Namespaces.Add("my", "http://foobar.com/");
doc.Schemas.Add(schema);
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(dec);
XmlElement root = doc.CreateElement("root");
root.SetAttribute("xmlns:my", "http://foobar.com/");
doc.AppendChild(root);
foreach (var item in GetItems())
{
XmlElement elem = doc.CreateElement("item");
elem.SetAttribute("id", item.id);
// Append body to elem
XmlElement body = doc.CreateElement("body");
body.InnerXml = item.Body; // Here is where I get the exception
elem.AppendChild(body);
// Append elem to root
root.AppendChild(elem);
}
Input from Item.Body is similar to
<aaa><bbb my:attr="55">Foo</bbb></aaa>
I expected the output to be similar to
<?xml version="1.0" encoding="utf-8"?>
<root my:attr="http://foobar.com/">
<item id="12345">
<body>
<aaa>
<bbb my:attr="55">Foo</bbb>
</aaa>
</body>
</item>
</root>
I'm open to alternatives to using this method. After I create the XmlDocument I prettyprint it, validate it against a schema and then push it out for the user to see.
The following is a workaround, best I can come up with:
XNamespace my = "http://foobar.com/";
var doc = new XDocument(new XElement("root",
new XAttribute(XNamespace.Xmlns + "my", my)));
var body = new XElement("body");
doc.Root.Add(new XElement("item", new XAttribute("id", 12345), body));
string innerItem = #"<aaa><bbb my:attr=""55"">Foo</bbb></aaa>";
string itemWrap = #"<wrap xmlns:my=""http://foobar.com/"">" + innerItem + "</wrap>";
XElement item = XElement.Parse(itemWrap);
body.Add(item.Element("aaa"));
Console.WriteLine(doc);

html to XSLT conversion using C#

I am trying to change a html page to a xslt page using C#,
for example if i have something like
#companyname#
i have to convert it into
<xsl:value-of select="test/companyname" />
I have a xsl file which has all these values. I dont want to replace the values here as they are to be further processed before replacing the original values.
The problem i am facing here is i have a trouble identifying(to replace the xml construct) if the value is in the attribute level of the tag or in the value level of the tag.
I am trying to use the regular expressions on it . Can someone help??
Html Agility Pack is the way to go. Don't forget to add the reference to it. This code illustrates one way of using HTML Agility Pack to create an XSLT which is what I think you want to do.
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(#"<html>" +
"<a href='#compantnameURL1#'>#companyname1#</a>" +
"<a href='#compantnameURL2#'>#companyname2#</a>" +
"</html>");
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
settings.IndentChars = (" ");
settings.Encoding = Encoding.UTF8;
using (XmlWriter writer = XmlWriter.Create(Console.Out, settings))
{
writer.WriteStartDocument();
writer.WriteStartElement("xsl", "stylesheet", "http://www.w3.org/1999/XSL/Transform");
writer.WriteStartElement("template", "http://www.w3.org/1999/XSL/Transform");
writer.WriteAttributeString("match", "/");
writer.WriteElementString("apply-templates", "http://www.w3.org/1999/XSL/Transform", "");
writer.WriteEndElement();
writer.WriteStartElement("template", "http://www.w3.org/1999/XSL/Transform");
writer.WriteAttributeString("match", "test/");
foreach (HtmlNode link in doc.DocumentNode.SelectNodes("//a"))
{
HtmlAttribute att = link.Attributes["href"];
writer.WriteStartElement("a");
writer.WriteStartElement("attribute", "http://www.w3.org/1999/XSL/Transform");
writer.WriteStartElement("value-of", "http://www.w3.org/1999/XSL/Transform");
writer.WriteAttributeString("select", att.Value);
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteStartElement("value-of", "http://www.w3.org/1999/XSL/Transform");
writer.WriteAttributeString("select", link.InnerText);
writer.WriteEndElement();
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteEndDocument();
}
I'm not aware of a component that will get you all to XSLT, but the HTML Agility Pack is wonderful for any sort of HTML manipulation. The parser will provide a complete object tree with attributes, tags, styles, etc clearly defined, and it's easily queryable with XSLT.
Also, for a good discussion of parsing HTML with regex, see the first answer on this post.

Linq to XML, C#

I have an xml in XDocument object (LINQ to XML). I need to add the namespace to each Xelement/node in the Xdocument.
I dont want to add in the below way. beceause i already have the xml in xdoc.
XDocument xDoc = new XDocument(
new XElement(ns + "root",
new XElement(ns + "person",
new XAttribute("id", 1),
new XElement(ns + "firstname", "jack"),
Below is the format i have
<root>
<person>1</person>
<firstname>jack</firstname>
</root>
I want to convert it to this below format
<emp:root>
<emp:person>1</emp:person>
<emp:firstname>jack</emp:firstname>
</emp:root>
foreach (var node in xDoc.Descendants())
{
node.Name = ns + node.Name.LocalName;
}
That should work:
Side note the namespace will only appear on the root node.

How do I add a namespace when creating an XML file?

I have to create an XML document in C#.
The root element has to look like this:
<valuation-request
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="valuations.xsd">
I'm using the following
XmlElement root = X.CreateElement("valuation-request");
root.SetAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.SetAttribute("xsi:noNamespaceSchemaLocation", "valuations.xsd");
However this produces
<valuation-request
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
noNamespaceSchemaLocation="valuations.xsd"> //missing the xsi:
What am I missing?
Use the overload of SetAttribute, that takes namespace as well:
root.SetAttribute("noNamespaceSchemaLocation",
"http://www.w3.org/2001/XMLSchema-instance",
"valuations.xsd"
);
With writer you add it like this:
var writerSettings = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
NewLineChars = Environment.NewLine,
NewLineHandling = NewLineHandling.Replace,
Encoding = new UTF8Encoding(false)
};
XmlWriter writer = XmlWriter.Create("C:\test.xml", writerSettings);
writer.WriteStartDocument(false);
writer.WriteStartElement("valuation-request");
writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
writer.WriteAttributeString("xsi", "noNamespaceSchemaLocation", null, "http://www.gzs.si/e-poslovanje/sheme/eSLOG_1-5_EnostavniRacun.xsd");
Recently, I have encountered same issue. To resolve it, I've just add the follow line:
XmlAttribute noNamespaceSchemaLocationAttr = xmlDoc.CreateAttribute("xsi", "noNamespaceSchemaLocation", "http://www.w3.org/2001/XMLSchema-instance");

Categories

Resources