So, I try creating Xml document with next code:
XNamespace spr1 = "urn:schemas-microsoft-com:office:spreadsheet";
XNamespace ex = "urn:schemas-microsoft-com:office:excel";
XNamespace spr2 = "urn:schemas-microsoft-com:office:spreadsheet";
XNamespace rec = "http://www.w3.org/TR/REC-html40";
var xworkbook = new XElement(spr1 + "Workbook");
xworkbook.Add(new XAttribute(XNamespace.Xmlns + "x", ex));
xworkbook.Add(new XAttribute(XNamespace.Xmlns +"ss", spr2));
xworkbook.Add(new XAttribute(XNamespace.Xmlns + "html", rec));
This code make next xml:
<ss:Workbook xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40">
<!--Xml body-->
</ss:Workbook>
But I expect this:
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
</Workbook>
How to build Workbook element without "ss" prefix and with needed "xmlns" attribute?
LINQ to XML uses the namespace prefix that is closest as it looks through all the attributes in reverse order from the current element to the root. So if you add the default namespace explicitly at the end, then Workbook will use that and not the ss prefix.
XNamespace ss = "urn:schemas-microsoft-com:office:spreadsheet";
XNamespace ex = "urn:schemas-microsoft-com:office:excel";
XNamespace html = "http://www.w3.org/TR/REC-html40";
var workbook = new XElement(
ss + "Workbook",
new XAttribute(XNamespace.Xmlns + "x", ex),
new XAttribute(XNamespace.Xmlns + "ss", ss),
new XAttribute(XNamespace.Xmlns + "html", html),
new XAttribute("xmlns", ss)
);
This gives you the XML below:
<Workbook xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns="urn:schemas-microsoft-com:office:spreadsheet" />
As stated in the comments, the two documents in your question are semantically the same. Any XML parser shouldn't care about the difference between the two documents.
I usually do it like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<Workbook xmlns=\"urn:schemas-microsoft-com:office:spreadsheet\"" +
" xmlns:x=\"urn:schemas-microsoft-com:office:excel\"" +
" xmlns:ss=\"urn:schemas-microsoft-com:office:spreadsheet\"" +
" xmlns:html=\"http://www.w3.org/TR/REC-html40\">" +
"</Workbook>";
XDocument doc = XDocument.Parse(xml);
XElement workbook = (XElement)doc.FirstNode;
XNamespace ssNs = workbook.GetNamespaceOfPrefix("ss");
XElement worksheet = new XElement(ssNs + "Worksheet");
workbook.Add(worksheet);
}
}
}
Related
In an xsl-fo file how can I remove some elements
Quickest way, perhaps not the most elegant :
XmlDocument xmlDoc = new XmlDocument();
StringBuilder xmlSb = new StringBuilder();
xmlSb.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
xmlSb.AppendLine("<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">");
xmlSb.AppendLine(" <fo:layout-master-set>");
xmlSb.AppendLine(" <fo:simple-page-master master-name=\"master\">");
xmlSb.AppendLine(" <fo:region-body margin-bottom=\"0.5in\" margin-top=\"0.9in\" margin-left=\"35pt\"/>");
xmlSb.AppendLine(" <fo:region-before region-name=\"xsl-region-before\" extent=\"0.9in\"/>");
xmlSb.AppendLine(" <fo:region-after region-name=\"xsl-region-after\" extent=\"0.5in\"/>");
xmlSb.AppendLine(" </fo:simple-page-master>");
xmlSb.AppendLine(" </fo:layout-master-set>");
xmlSb.AppendLine(" <fo:page-sequence master-reference=\"master\"/>");
xmlSb.AppendLine("</fo:root>");
// Load xml from string
xmlDoc.LoadXml(xmlSb.ToString());
Console.WriteLine("----- Original xml -----");
Console.WriteLine(xmlSb.ToString());
// Select region-before node
XmlNode regionBeforeNode = xmlDoc.SelectSingleNode("//*[local-name()='region-before']");
// Remove region-before node
regionBeforeNode.ParentNode.RemoveChild(regionBeforeNode);
// Select region-after node
XmlNode regionAfterNode = xmlDoc.SelectSingleNode("//*[local-name()='region-after']");
// Remove region-after node
regionAfterNode.ParentNode.RemoveChild(regionAfterNode);
Console.WriteLine("----- Nodes removed -----");
StringBuilder sbOut = new StringBuilder();
// Pretty indented output
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
NewLineChars = "\r\n",
NewLineHandling = NewLineHandling.Replace
};
using (XmlWriter writer = XmlWriter.Create(sbOut, settings))
{
xmlDoc.Save(writer);
}
Console.WriteLine(sbOut.ToString ());
Try xml linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication11
{
class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<fo:root xmlns:fo=\"http://www.w3.org/1999/XSL/Format\">" +
" <fo:layout-master-set>" +
" <fo:simple-page-master master-name=\"master\">" +
" <fo:region-body margin-bottom=\"0.5in\" margin-top=\"0.9in\" margin-left=\"35pt\"/>" +
" </fo:simple-page-master>" +
" </fo:layout-master-set>" +
" <fo:page-sequence master-reference=\"master\"/>" +
"</fo:root>";
XDocument doc = XDocument.Parse(xml);
XNamespace nsFo = doc.Root.GetNamespaceOfPrefix("fo");
XElement regionBody = doc.Descendants(nsFo + "region-body").FirstOrDefault();
regionBody.Add(new XElement(nsFo + "test", new object[] { new XAttribute("name", "John")}));
}
}
}
Question update: im very sorry if my question is not clear
here is the code im using right now
XDocument doc = XDocument.Parse(framedoc.ToString());
foreach (var node in doc.Descendants("document").ToList())
{
XNamespace ns = "xsi";
node.SetAttributeValue(ns + "schema", "");
node.Name = "alto";
}
and here is the output
<alto p1:schema="" xmlns:p1="xsi">
my goal is like this
xsi:schemaLocation=""
where does the p1 and xmlns:p1="xsi" came from?
When you write
XNamespace ns = "xsi";
That's creating an XNamespace with a URI of just "xsi". That's not what you want. You want a namespace alias of xsi... with the appropriate URI via an xmlns attribute. So you want:
XDocument doc = XDocument.Parse(framedoc.ToString());
foreach (var node in doc.Descendants("document").ToList())
{
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
node.SetAttributeValue(XNamespace.Xmnls + "xsi", ns.NamespaceName);
node.SetAttributeValue(ns + "schema", "");
node.Name = "alto";
}
Or better, just set the alias at the root element:
XDocument doc = XDocument.Parse(framedoc.ToString());
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
doc.Root.SetAttributeValue(XNamespace.Xmlns + "xsi", ns.NamespaceName);
foreach (var node in doc.Descendants("document").ToList())
{
node.SetAttributeValue(ns + "schema", "");
node.Name = "alto";
}
Sample creating a document:
using System;
using System.Xml.Linq;
public class Test
{
static void Main()
{
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
XDocument doc = new XDocument(
new XElement("root",
new XAttribute(XNamespace.Xmlns + "xsi", ns.NamespaceName),
new XElement("element1", new XAttribute(ns + "schema", "s1")),
new XElement("element2", new XAttribute(ns + "schema", "s2"))
)
);
Console.WriteLine(doc);
}
}
Output:
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<element1 xsi:schema="s1" />
<element2 xsi:schema="s2" />
</root>
How do I add the char : to an XML element attribute?
Here is how the output should look like
<alto xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.loc.gov/standards/alto/ns-v3#"
xsi:schemaLocation="http://www.loc.gov/standards/alto/ns-v3# http://www.loc.gov/standards/alto/v3/alto-3-1.xsd" SCHEMAVERSION="3.1"
xmlns:xlink="http://www.w3.org/1999/xlink">
and so far this is my code
var z = doc.Descendants("alto").First();
XNamespace ns = "http://www.w3.org/2001/XMLSchema-instance";
z.Add(new XAttribute(XNamespace.Xmlns + "xsi", ns.NamespaceName));
I tried this code, but it gives me error
new XAttribute("xmlns", "http://www.loc.gov/standards/alto/ns-v3#")
and here is the error message:
The prefix '' cannot be redefined from '' to 'http://www.loc.gov/standards/alto/ns-v3#' within the same start element tag
You should put default namespace last. For complex namespaces like yours I usually just parse the string like code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string xml =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>" +
"<alto xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
" xmlns=\"http://www.loc.gov/standards/alto/ns-v3#\"" +
" xsi:schemaLocation=\"http://www.loc.gov/standards/alto/ns-v3# http://www.loc.gov/standards/alto/v3/alto-3-1.xsd\" SCHEMAVERSION=\"3.1\"" +
" xmlns:xlink=\"http://www.w3.org/1999/xlink\">" +
"</alto>";
XDocument doc = XDocument.Parse(xml);
XElement root = doc.Root;
XNamespace ns = root.GetDefaultNamespace();
XNamespace nsXsi = root.GetNamespaceOfPrefix("xsi");
XNamespace nsSchemaLocation = root.GetNamespaceOfPrefix("schemaLocation");
XNamespace nsXlink = root.GetNamespaceOfPrefix("xlink");
}
}
}
I am having trouble creating an XML document using LINQ.
The XML file I need to create has a root element of "ClinicalDocument".
The XML needs to be as follows
<?xml version="1.0" encoding="utf-8"?>
<ClinicalDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:hl7-org:v3"
xmlns:voc="urn:hl7-org:v3/voc"
xmlns:sdtc="urn:hl7-org:sdtc">
<!-- Rest of the document here. -->
</ClinicalDocument>
The code I have in trying to do this is
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
XDeclaration dec = new XDeclaration("1.0", "UTF-8", null);
XDocument xDoc = new XDocument(dec,null);
XElement cDoc = new XElement("ClinicalDocumnet");
xDoc.Add(cDoc);
cDoc.Add(new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName));
cDoc.Add(new XAttribute("xmlns","urn:hl7-org:v3"));
cDoc.Add(new XAttribute(XNamespace.Xmlns + "stdc","urn:hl7-org:sdtc"));
cDoc.Add(new XAttribute(XNamespace.Xmlns + "voc","urn:hl7-org:v3/voc"));
xDoc.Save("C:\\test\\test.xml");
I get an exception when trying to save the file.
{"The prefix '' cannot be redefined from '' to 'urn:hl7-org:v3' within the same start element tag."}
XNamespace ns = "urn:hl7-org:v3";
xDoc = new XDocument(dec, null);
cDoc = new XElement(ns + "ClinicalDocument");
xDoc.Add(cDoc);
cDoc.Add(new XAttribute(XNamespace.Xmlns + "xsi", "http://www.w3.org/2001/XMLSchema-instance"));
cDoc.Add(new XAttribute(XNamespace.Xmlns + "stdc","urn:hl7-org:sdtc"));
cDoc.Add(new XAttribute(XNamespace.Xmlns + "voc","urn:hl7-org:v3/voc"));
I need to generate xml like that:
<urlset xmlns:video="http://www.google.com/schemas/sitemap-video/1.1" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://blabla</loc>
<video:video>
<video:player allow_embed="yes">http://blablabla</video:player_loc>
</video:video>
</url>
I can't figure out the way to work with namespaces. I can't even create urlset element properly, I'm trying:
XNamespace _defaultNamespace = "http://www.sitemaps.org/schemas/sitemap/0.9";
XNamespace _videoNameSpace = "http://www.google.com/schemas/sitemap-video/1.1";
new XElement("urlset",new XAttribute(_defaultNamespace+"video",_defaultNamespace))
and it generates:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<urlset p1:video="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:p1="http://www.sitemaps.org/schemas/sitemap/0.9">
what's that p1 thing?
Namespace attributes are in xmlns namespace, so you should use
XNamespace.Xmlns+ attributeName for declaring namespaces:
XNamespace ns = "http://www.sitemaps.org/schemas/sitemap/0.9";
XNamespace video = "http://www.google.com/schemas/sitemap-video/1.1";
var urlset = new XElement(ns + "urlset",
new XAttribute(XNamespace.Xmlns + "video", video));
Produces
<urlset xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" />
Complete xml generation will look like:
var urlset = new XElement(ns + "urlset",
new XAttribute(XNamespace.Xmlns + "video", video),
new XElement(ns + "url",
new XElement(ns + "loc", "http:/blabla"),
new XElement(video + "video",
new XElement(video + "player",
new XAttribute("allow_embed", "yes"),
"http:/blabla"))));