I'd like to write out the following XAML using LINQ to XML via C#.
<Activity x:Class="WorkflowConsoleApplication1.Activity1" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation"> </Activity>
How do I specify the XNamespace for doing this to achieve the above output?
This code will do it:
var el = new XElement(
"Activity",
new XAttribute(XName.Get("Class", "SomeNamespace"), "WorkflowConsoleApplication1.Activity1"),
new XAttribute(
XName.Get("VisualBasic.Settings", "SomeOtherNamespace"),
"Assembly references and imported namespaces for internal implementation"));
Console.WriteLine(el.ToString());
Notice how you do not specify the prefixes, but rather the namespaces that these attributes belong to. This is by design and consistent with the XML spec. Prefixes will be generated automatically, or picked up from the containing element if this element is a child of another element that has already defined a prefix for the namespaces you're using.
Related
I know how I can create a new XML file, set the declaration, the name space and add new elements to the root. However, if I want to append elements to an existing file it is added xmlns as attribute of the new element:
<NewElement p3:id="1" idAux="A1" xmlns:p3="http://xyz.com/2006/bbb" xmlns="">
I try to use the loaded the namespace of the document, but that does not work.
How can I add new elements to an existing file and respect the format of the existing elements?
I am using linq to xml.
Thanks.
Try the following code:
// Assume 'el' is the new element that's created.
XElement el = new XElement("NewElement", new XAttribute("{p3}id", 1), new XAttribute("idAux", "A1"));
The above should create the following:
<NewElement p3:id="1" idAux="A1">
Note that the namespace p3 may be created on the document root element--I'm not sure about that. Also I know that with the old System.Xml API, if you didn't specify a default namespace for your document, then the XmlSerializer would add the xsi and xsd namespaces automatically.
I know in the old Xml API, the correct way to specify a default namespace was to add a XmlNamespaceManager-type property to your class (which is a container for an array of XmlQualifiedName objects) and add a XmlQualifiedName object as follows: new XmlQualifiedName(string.Empty, "urn:your-namespace-name"). You probably need to do something similar for your document using XML-to-LINQ.
I have a SO post about that: XmlSerializer: remove unnecessary xsi and xsd namespaces. HTH.
I am using the XmlWriter class to create an XML document.
I am able to produce the document as required except for the root element.
I cannot seem to be able to create the the root element with the required attributes which is proving troublesome because of the namespaces and prefixes that are needed.
What I am trying to do is produce output like the following:
<prx:rootname xmlns:prx="url1" xmlns:xsi="url2" xsi:schemaLocation="url3">
The above is a condensed example of the actual root element needed, the actual URLs are quite verbose for example.
FYI, all other child elements use the same prefix as the root element.
Can I use this class or would I have to use another method to generate the desired XML output?
I have an XPath query which looks right to me, but isn't returning any results.
The XML document it's being tested against:
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Deployment.Parts>
<AssemblyPart x:Name="foo" Source="foo.dll" />
</Deployment.Parts>
</Deployment>
The code:
Xml = new XmlDocument();
Xml.LoadXml(text);
Manager = new XmlNamespaceManager(Xml.NameTable);
//use constants for namespaces to make more readable
Manager.AddNamespace("a", NS_DEPLOYMENT_2007); //use 'a' for default namespace here so xpath is easier
Manager.AddNamespace("x", NS_XAML_2006);
string xpath="//a:Deployment.Parts/a:AssemblyPart[#a:Source='foo.dll']";
var tmp = Xml.SelectNodes(xpath, Manager);
What is wrong with my XPath query here?
You need to remove the namespace prefix from your attribute:
string xpath="//a:Deployment.Parts/a:AssemblyPart[#Source='foo.dll']";
You only need to specify the namespace for the attribute if it explicitly has a namespace defined, so when you would want to query the Name attribute, you would have to add it:
string xpath="//a:Deployment.Parts/a:AssemblyPart[#x:Name='foo']";
I suspect this part is your problem:
#a:Source='foo.dll'
Unlike element names, attribute names don't inherit a namespace. Your document doesn't specify a namespace for the attribute, so I don't think you should do so either.
Try just:
#Source='foo.dll'
(As an aside, I would personally use LINQ to XML instead of XPath - I find it generally simpler. YMMV, but it may be worth considering - if you're using .NET 3.5 or higher, of course.)
From "Namespaces in XML 1.0 (3rd edition)" section 6.2 (emphasis mine):
The scope of a default namespace declaration extends from the beginning of the start-tag in which it appears to the end of the corresponding end-tag, excluding the scope of any inner default namespace declarations. In the case of an empty tag, the scope is the tag itself.
A default namespace declaration applies to all unprefixed element names within its scope. Default namespace declarations do not apply directly to attribute names; the interpretation of unprefixed attributes is determined by the element on which they appear.
Suppose I have such elements in my XML document:
<xs:appinfo>
<CustomXML>
<Something>something</Something>
</CustomXML>
</xs:appinfo>
"xs" is declared as the default schema namespace. My question is: how would a parser interpret the inner elements of xs:appinfo? In which namespace do they belong?
I ask because I'm parsing the code in C# and it keeps adding "xmlns="" " to the CustomXML element, which makes me assume that otherwise it'd treat these elements as schema elements.
According to §6.2 Namespace Defaulting of Namespaces in XML 1.0 (Third Edition):
The scope of a default namespace declaration extends from the beginning of the start-tag in which it appears to the end of the corresponding end-tag, excluding the scope of any inner default namespace declarations. […]
A default namespace declaration applies to all unprefixed element names within its scope.
That means that elements with no namespace prefix are interpreted as being in the default namespace. Default namespace is usually defined on the first element of the document and look like this:
<element xmlns="namespace-uri">
The library redefines the default namespace when it's necessary, that is, when you add an element to the document with no namespace. In other words, such element is not in the default namespace, so the library solves this by adding xmlns="" to that element, which redefined the default namespace for this element and all its descendants to "no namespace".
If you want to add element that is in the default namespace, you have to specify it explicitly. For example, in LINQ to XML:
XDocument doc = …;
var ns = doc.Root.GetDefaultNamespace();
var newElement = new XElement(ns + "foo"));
So I have xml that looks like this:
<todo-list>
<id type="integer">#{id}</id>
<name>#{name}</name>
<description>#{description}</description>
<project-id type="integer">#{project_id}</project-id>
<milestone-id type="integer">#{milestone_id}</milestone-id>
<position type="integer">#{position}</position>
<!-- if user can see private lists -->
<private type="boolean">#{private}</private>
<!-- if the account supports time tracking -->
<tracked type="boolean">#{tracked}</tracked>
<!-- if todo-items are included in the response -->
<todo-items type="array">
<todo-item>
...
</todo-item>
<todo-item>
...
</todo-item>
...
</todo-items>
</todo-list>
How would I go about using .NET's serialization library to deserialize this into C# objects?
Currently I'm using reflection and I map between the xml and my objects using the naming conventions.
Create a class for each element that has a property for each element and a List or Array of objects (use the created one) for each child element. Then call System.Xml.Serialization.XmlSerializer.Deserialize on the string and cast the result as your object. Use the System.Xml.Serialization attributes to make adjustments, like to map the element to your ToDoList class, use the XmlElement("todo-list") attribute.
A shourtcut is to load your XML into Visual Studio, click the "Infer Schema" button and run "xsd.exe /c schema.xsd" to generate the classes. xsd.exe is in the tools folder. Then go through the generated code and make adjustments, such as changing shorts to ints where appropriate.
Boils down to using xsd.exe from tools in VS:
xsd.exe "%xsdFile%" /c /out:"%outDirectory%" /l:"%language%"
Then load it with reader and deserializer:
public GeneratedClassFromXSD GetObjectFromXML()
{
var settings = new XmlReaderSettings();
var obj = new GeneratedClassFromXSD();
var reader = XmlReader.Create(urlToService, settings);
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(GeneratedClassFromXSD));
obj = (GeneratedClassFromXSD)serializer.Deserialize(reader);
reader.Close();
return obj;
}
Deserialize any object, as long as the type T is marked Serializable:
function T Deserialize<T>(string serializedResults)
{
var serializer = new XmlSerializer(typeof(T));
using (var stringReader = new StringReader(serializedResults))
return (T)serializer.Deserialize(stringReader);
}
Well, you'd have to have classes in your assembly that match, roughly, the XML (property called Private, a collection property called ToDo, etc).
The problem is that the XML has elements that are invalid for class names. So you'd have to implement IXmlSerializable in these classes to control how they are serialized to and from XML. You might be able to get away with using some of the xml serialization specific attributes as well, but that depends on your xml's schema.
That's a step above using reflection, but it might not be exactly what you're hoping for.
Checkout http://xsd2code.codeplex.com/
Xsd2Code is a CSharp or Visual Basic Business Entity class Generator from XSD schema.
There are a couple different options.
Visual Studio includes a command line program called xsd.exe. You use that program to create a schema document, and use the program again on the schema document to creates classes you can use with system.xml.serialization.xmlserializer
You might just be able to call Dataset.ReadXml() on it.
i had the same questions few years back that how abt mapping xml to C# classes or creating C# classes which are mapped to our XMLs, jst like we do in entity Framework (we map tables to C# classes). I created a framework finally, which can create C# classes out of your XML and these classes can be used to read/write your xml. Have a look