I am trying to insert xsi and xsmln data into XML, I have used various ways but I could not get it, I also need to insert prefixes. Next I show my code where I get the XML and I also show you the structure I get, and at the end I show you what I really want to get.
This is the code where I get the XML:
string txtXML = XmlfrommyfunctionSQL(); // here retrieve from sqlserver
XDocument doc;
using (StringReader s = new StringReader(txtXML))
{
doc = XDocument.Load(s);
}
doc.Declaration = new XDeclaration("1.0", "UTF-8", null);
string targetxml = doc.ToString();
targetxml = doc.Declaration.ToString() + Environment.NewLine + doc.ToString();
This is the XML I get in string targetxml:
<?xml version="1.0" encoding="UTF-8"?>
<Invoice>
<UBLxtensions>
<UBLExtension>
<AccountingSupplierParty>
<AdditionalAccountID>1</AdditionalAccountID>
<Party>
<PartyName>
<Name>GRUPO ERB</Name>
</PartyName>
<PhysicalLocation>
<Address>
<ID>11001</ID>
<Country>
<IdentificationCode>CO</IdentificationCode>
</Country>
</Address>
</PhysicalLocation>
</Party>
</AccountingSupplierParty>
</UBLExtension>
</UBLExtensions>
</Invoice>
But I need to insert xsi:schemaLocation and xmlns, and insert prefix in Elemnts, how do I do that ?
I expect to get this:
<?xml version="1.0" encoding="UTF-8"?>
<Invoice Invoice xsi:schemaLocation="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2
http://docs.oasis-open.org/ubl/os-UBL-2.1/xsd/maindoc/UBL-Invoice-2.1.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xades141="http://uri.etsi.org/01903/v1.4.1#"
xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"
xmlns:sts="http://www.dianees.com/contra/acturaeca/v1/Structures"
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
<ext:UBLExtensions>
<ext:UBLExtension>
<cac:AccountingSupplierParty>
<cbc:AdditionalAccountID>1</cbc:AdditionalAccountID>
<cac:Party>
<cac:PartyName>
<cbc:Name>GRUPO ERB</cbc:Name>
</cac:PartyName>
<cac:PhysicalLocation>
<cac:Address>
<cbc:ID>11001</cbc:ID>
<cac:Country>
<cbc:IdentificationCode>CO</cbc:IdentificationCode>
</cac:Country>
</cac:Address>
</cac:PhysicalLocation>
</cac:Party>
</cac:AccountingSupplierParty>
</ext:UBLExtension>
</ext:UBLExtensions>
</Invoice>
please show me how to make one and I will do the rest
This will give you an idea how to solve your problem. I created a small example. it is far from perfect but is shows in basic which steps to take.
first the no namespace xsd is defined as:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Parent">
<xs:complexType>
<xs:sequence>
<xs:element name="Child1" type="xs:string"/>
<xs:element name="Child2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
then because of the different namespaces in your message i've created the same message with different namespaces. Each namespace is a different file.
Root.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/Root" xmlns:p="http://tempuri.org/Parent" targetNamespace="http://tempuri.org/Root" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:import namespace="http://tempuri.org/Parent" schemaLocation="Parent.xsd"/>
<xs:element name="Root" type="p:ParentType"/>
</xs:schema>
parent.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/Parent" xmlns:ch="http://tempuri.org/Child" targetNamespace="http://tempuri.org/Parent" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:import namespace="http://tempuri.org/Child" schemaLocation="Child.xsd"/>
<xs:complexType name="ParentType">
<xs:sequence>
<xs:element name="Parent" type="ch:ChildType"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Child.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns="http://tempuri.org/Child1" targetNamespace="http://tempuri.org/Child">
<xs:complexType name="ChildType">
<xs:sequence>
<xs:element name="Child1" type="xs:string"/>
<xs:element name="Child2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Next step is to create class files using xsd.exe. I use a bat file to execute te commands.
#echo off
set exepad=C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\xsd.exe
set sourcepad=..\..\
set xsdpad=%sourcepad%\console\xsd
set Outpad=%sourcepad%\console\generated
Set NameSpace=Console.generated
"%exepad%" "%xsdpad%\NoNSmessage.xsd" /c /n:%NameSpace% /o:%Outpad%
"%exepad%" "%xsdpad%\Child.xsd" "%xsdpad%\Parent.xsd" "%xsdpad%\Root.xsd" /c /n:%NameSpace% /o:%Outpad%
pause
Then import the generated class files into your project so they can be used.
this is an example how you can map the fields from the source to the target.
static void Main(string[] args)
{
const string msg1 = "<Root><Parent><Child1>First</Child1><Child2>Second</Child2></Parent></Root>";
//deserialize xml string into class object.
XmlSerializer deserializer = new XmlSerializer(typeof(Root));
var reader = new StringReader(msg1);
var noNamespaceRoot = (Root)deserializer.Deserialize(reader);
//map the fields from the nonamespace msg to the msg with a namespace
var namespaceRoot = new ParentType();
namespaceRoot.Parent = new ChildType();
namespaceRoot.Parent.Child1 = noNamespaceRoot.Parent.Child1;
namespaceRoot.Parent.Child2 = noNamespaceRoot.Parent.Child2;
//serialize the class object to a string.
var serializer = new XmlSerializer(typeof(ParentType));
var sww = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(sww))
{
serializer.Serialize(writer, namespaceRoot);
}
System.Console.WriteLine(sww.ToString());
}
the output will be:
<?xml version="1.0" encoding="utf-16"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/Root">
<Parent xmlns="http://tempuri.org/Parent">
<Child1 xmlns="http://tempuri.org/Child">First</Child1>
<Child2 xmlns="http://tempuri.org/Child">Second</Child2>
</Parent>
</Root>
Related
I am using Visual Studio 2015.
I apologize for the poorly named "firstName" element. It should have been "fullName", but since I already generated the class for the schema, and this is just for my own learning, I left it as is.
I have an XML schema here:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="address-schema"
targetNamespace="http://tempuri.org/address-schema.xsd"
elementFormDefault="qualified"
attributeFormDefault="qualified"
xmlns:addr="http://tempuri.org/address-schema.xsd"
xmlns:mstns="http://tempuri.org/address-schema.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="address">
<xs:complexType>
<xs:sequence>
<xs:element name="firstName">
<xs:complexType>
<xs:sequence>
<xs:element name="first" type="addr:nameComponent"/>
<xs:element name="middle" type="addr:nameComponent" minOccurs="0"/>
<xs:element name="last" type="addr:nameComponent"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="nameComponent">
<xs:simpleContent>
<xs:extension base="xs:string"/>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
And an XML file that I think conforms to the schema:
<?xml version="1.0" encoding="utf-8" ?>
<addr:address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tempuri.org/address-schema.xsd address-schema.xsd"
xmlns:addr="http://tempuri.org/address-schema.xsd">
<addr:firstName>
<addr:first>Some</addr:first>
<addr:middle>Bodys</addr:middle>
<addr:last>Name</addr:last>
</addr:firstName>
</addr:address>
And the code that is attempting to validate the XML is here (note that the "address" class that the XML file is getting deserialized into is an auto generated class from xsd.exe):
address address;
var xmlSchemaSerializer = new XmlSerializer(typeof(XmlSchema));
var addressXmlSerializer = new XmlSerializer(typeof(address));
var schemas = new XmlSchemaSet();
XmlSchema schema;
using (var xsdStream = File.OpenRead("address-schema.xsd"))
{
schema = (XmlSchema)xmlSchemaSerializer.Deserialize(xsdStream);
}
schemas.Add(schema);
var settings = new XmlReaderSettings
{
Schemas = schemas,
ValidationType = ValidationType.Schema,
ValidationFlags = XmlSchemaValidationFlags.ProcessIdentityConstraints | XmlSchemaValidationFlags.ReportValidationWarnings | XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation
};
settings.ValidationEventHandler += (sender, arguments) =>
{
throw new XmlSchemaValidationException(arguments.Message);
};
using(Stream addressXmlStream = File.OpenRead("address-doc.xml"))
using (XmlReader reader = XmlReader.Create(addressXmlStream, settings))
{
address = (address)addressXmlSerializer.Deserialize(reader);
}
Console.WriteLine(address.firstName.first.Value == "Some" ? "Success!" : "Fail");
Console.ReadKey();
The exception ('System.Xml.Schema.XmlSchemaValidationException'The global element 'http://tempuri.org/address-schema.xsd:address' has already been declared.) is thrown in the ValidationEventHandler.
Any help or suggestions would be appreciated. Thanks in advance!
The cause of your exception is that your document has a schema location hint that loads the schema, but you've already loaded it.
Either don't pre-load the schema or remove the xsi:schemaLocation attribute from your document.
I have to parse a XML where the xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" namespace is missing, so the xml looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<program>
<scriptList>
<script type="StartScript">
<isUserScript>false</isUserScript>
</script>
</scriptList>
</program>
but should look like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<program xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<scriptList>
<script xsi:type="StartScript">
<isUserScript>false</isUserScript>
</script>
</scriptList>
</program>
The type attribute ensures the correct subclass e.g.
class StartScript : script
{...}
The parser is auto generated from an handwritten xsd via $> xsd.exe a.xsd /classes (.Net).
Here is the xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="qualified">
<!-- Main element -->
<xs:element name="program">
<xs:complexType>
<xs:sequence>
<xs:element name="scriptList">
<xs:complexType>
<xs:sequence>
<xs:element name="script" type="script" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="script" />
<xs:complexType name="StartScript">
<xs:complexContent>
<xs:extension base="script">
<xs:all>
<xs:element name="isUserScript" type="xs:boolean"></xs:element>
</xs:all>
</xs:extension>
</xs:complexContent>
</xs:complexType>
A simple solution is to run a string-replace (" type=\"" to " xsi:type=\"") on the input XML but this is pretty ugly.
Is there a better solution?
You can load your XML into an intermediate LINQ to XML XDocument, fix the attribute namespaces on the <script> elements, then deserialize directly to your final class:
// Load to intermediate XDocument
XDocument xDoc;
using (var reader = XmlReader.Create(f))
xDoc = XDocument.Load(reader);
// Fix namespace of "type" attributes
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
foreach (var element in xDoc.Descendants("script"))
{
var attr = element.Attribute("type");
if (attr == null)
continue;
var newAttr = new XAttribute(xsi + attr.Name.LocalName, attr.Value);
attr.Remove();
element.Add(newAttr);
}
// Deserialize directly to final class.
var program = xDoc.Deserialize<program>();
Using the extension method:
public static class XObjectExtensions
{
public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null)
{
if (element == null)
throw new ArgumentNullException();
using (var reader = element.CreateReader())
return (T)(serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader);
}
}
I am building a web service in .NET that will pass data back and forth via XML. I would like to validate the XML in the incoming requests using an XSD that I have defined.
Here is the XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="POSearch">
<xs:sequence minOccurs="0" maxOccurs="10">
<xs:element name="POID" type="xs:positiveInteger"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Here is the XML:
<POSearch>
<POID>1</POID>
<POID>2</POID>
</POSearch>
Here is the validation code in C#:
static void Main(string[] args){
XmlSchemaSet iSchemas = new XmlSchemaSet();
iSchemas.Add(string.Empty, #"...xsd file location");
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
settings.Schemas.Add(iSchemas);
XmlReader reader = XmlReader.Create(#"...xml file location", settings);
try {
while(reader.Read())
;
}
catch(Exception ex) {
Console.WriteLine(ex.Message);
}
}
private static void ValidationCallBack(object sender, ValidationEventArgs args) {
if(args.Severity == XmlSeverityType.Warning)
Console.WriteLine("\tWarning: Matching schema not found. No validation occurred." + args.Message);
else
Console.WriteLine("\tValidation error: " + args.Message);
}
I feel like I had this working before and I'm not completely sure why this isn't working now. Whenever I run this I get the following Exception Message:
Validation error: The 'POSearch' element is not declared.
Have I defined my XSD wrong? Is my validation code wrong? The elements are all clearly there. Any help pointing me in the right direction is greatly appreciated.
You have the type declared but no element declared of that type.
Add an element declaration:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="POSearch" type="POSearch"/>
<xs:complexType name="POSearch">
<xs:sequence minOccurs="0" maxOccurs="10">
<xs:element name="POID" type="xs:positiveInteger"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
Try this:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="POSearch">
<xs:sequence minOccurs="0" maxOccurs="10">
<xs:element name="POID" type="xs:positiveInteger"/>
</xs:sequence>
</xs:complexType>
<xs:element name="POSearch" type="POSearch"/>
</xs:schema>
I have 2 xsd files content in a dictionary. I want to merge both the contents and create one xsd file.
1st xsd content from dictionary has a import tag pointing to 2nd xsd in the dictionary.
1st xsd -
<?xml version="1.0" encoding="IBM437"?>
<xs:schema xmlns:tns="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/EnrichedMessageXML" targetNamespace="http://schemas.microsoft.com/BizTalk/EDI/EDIFACT/2006/Enr
ichedMessageXML" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="COMP.EDI._00401._810.Schemas.Headers" namespace="http://EDI/Headers" />
<xs:element name="X12EnrichedMessage">
<xs:complexType>
<xs:sequence>
<xs:element xmlns:q1="http://EDI/Headers" ref="q1:Headers" />
<xs:element name="TransactionSet">
<xs:complexType>
<xs:sequence>
<xs:element xmlns:q2="http://schemas.microsoft.com/BizTalk/EDI/X12/2006" ref="q2:X12_00401_810" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
2nd sxd -
<?xml version="1.0" encoding="IBM437"?>
<xs:schema xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns="http://EDI/Headers" xmlns:xs="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://EDI/Headers">
<xs:element name="Headers">
// Some content here
</xs:element>
</xs:schema>
desired xsd I want is the merger of both the xsd documents.
I am following this : http://msdn.microsoft.com/en-us/library/ms256237%28v=vs.110%29.aspx article, I am able to add the schemas to schemaset object also, but when I am using RecurseExternals function (from the article) this is not showing the merged xsd but 2 different xsd.
my block of code -
XmlSchemaSet schemaSet = new XmlSchemaSet();
// This prevents schemaLocation and Namespace warnings
// at this point we already have the schema from schemaLocation.
//schemaSet.XmlResolver = null;
schemaSet.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
// add schema in schema set from schemacollection object
foreach (var item in schemaCollection)
{
schemaSet.Add(item.Key, new XmlTextReader(new StringReader(item.Value)));
}
schemaSet.Compile();
XmlSchema mainXmlSchema = null;
XmlSchemaImport import = new XmlSchemaImport();
foreach (XmlSchema sch in schemaSet.Schemas())
{
// pick the main schema from the schemaset to include
// other schemas in the collection.
if (sch.TargetNamespace == mainSchemaNS)
{
mainXmlSchema = sch;
}
else
{
import.Namespace = sch.TargetNamespace;
import.Schema = sch;
mainXmlSchema.Includes.Add(import);
}
}
schemaSet.Reprocess(mainXmlSchema);
schemaSet.Compile();
RecurseExternals(mainXmlSchema);
am I doing anything wrong ?
I'm trying to deserialize XML into a C# object
I am getting the error:There is an error in XML document (3, 2).
Cannot seem to fix it! Here is the code:
The XSD is:
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid XML Studio 2012 Developer Edition (Trial) 10.0.2.3955 (http://www.liquid-technologies.com)-->
<xs:schema xmlns:tns="http://www.adamroe.com/xsd/cameras.xsd" elementFormDefault="qualified" targetNamespace="http://www.adamroe.com/xsd/cameras.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="CameraBase">
<xs:complexType>
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="Cameras">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="Camera" type="tns:CameraType" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="CameraType">
<xs:sequence>
<xs:element name="Make" type="xs:string" />
<xs:element name="Model" type="xs:string" />
<xs:element name="Variable1" type="xs:double" />
<xs:element name="Variable2" type="xs:double" />
</xs:sequence>
</xs:complexType>
</xs:schema>
The XML is:
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid XML Studio 2012 Developer Edition (Trial) 10.0.2.3955 (http://www.liquid-technologies.com) -->
<aroe:CameraBase xmlns:aroe="http://www.adamroe.com/xsd/cameras.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.adamroe.com/xsd/cameras.xsd C:\Users\Adam\Desktop\Cameras.xsd">
<aroe:Cameras>
<aroe:Camera>
<aroe:Make>SONY</aroe:Make>
<aroe:Model>DSC-W130</aroe:Model>
<aroe:Variable1>0.6352</aroe:Variable1>
<aroe:Variable2>22.375</aroe:Variable2>
</aroe:Camera>
<aroe:Camera>
<aroe:Make>Panasonic</aroe:Make>
<aroe:Model>DMC-FX30</aroe:Model>
<aroe:Variable1>0.8869</aroe:Variable1>
<aroe:Variable2>24.73</aroe:Variable2>
</aroe:Camera>
<aroe:Camera>
<aroe:Make>Olympus</aroe:Make>
<aroe:Model>X450</aroe:Model>
<aroe:Variable1>0.6003</aroe:Variable1>
<aroe:Variable2>20.654</aroe:Variable2>
</aroe:Camera>
<aroe:Camera>
<aroe:Make>Fujifilm</aroe:Make>
<aroe:Model>FinePix S9600</aroe:Model>
<aroe:Variable1>1.0024</aroe:Variable1>
<aroe:Variable2>35.704</aroe:Variable2>
</aroe:Camera>
<aroe:Camera>
<aroe:Make>Canon</aroe:Make>
<aroe:Model>EOS 400D</aroe:Model>
<aroe:Variable1>1.5143</aroe:Variable1>
<aroe:Variable2>69.409</aroe:Variable2>
</aroe:Camera>
</aroe:Cameras>
</aroe:CameraBase>
The class is:
public class Camera
{
public string Make;
public string Model;
public double Variable1;
public double Variable2;
}
Deserialize code:
public class PopulateXML
{
public void DeserializeObject(string filenameXML)
{
Console.WriteLine("Reading with XmlReader");
// Create an instance of the XmlSerializer specifying type and namespace.
XmlSerializer serializer = new
XmlSerializer(typeof(List<Camera>));
// A FileStream is needed to read the XML document.
FileStream fs = new FileStream(filenameXML, FileMode.Open);
XmlReader reader = new XmlTextReader(fs);
// Declare an object variable of the type to be deserialized.
List<Camera> i;
// Use the Deserialize method to restore the object's state.
i = (List<Camera>)serializer.Deserialize(reader);
}
}
Main:
PopulateXML x = new PopulateXML();
// Read a purchase order.
x.DeserializeObject("Cameras.xml");
The exception is thrown on: i = (List)serializer.Deserialize(reader);
XmlSerializer serializer = new XmlSerializer(typeof(Camera));
Stream fs = File.OpenRead(filenameXMLpath);
// Use the Deserialize method to restore the object's state.
Camera cam = serializer.Deserialize(fs) as Camera;
This will definitely work for you. In your case it was not working because you were type casting it to the incorrect data type i.e., List. This error generally pops-up whenever developer type cast deserialized object to incorrect data type.
You could use LinqToXml and these extensions: http://searisen.com/xmllib/extensions.wiki to parse the Xml easily.
XElement root = XElement.Load(file); // or .Parse(string)
List<Camera> cameras = root.GetEnumerable("Cameras/Camera", x => new Camera()
{
Make = x.Get("Make", string.Empty),
Model = x.Get("Model", string.Empty),
Variable1 = x.Get<double>("Variable1", 0),
Variable2 = x.Get<double>("Variable2", 0)
}).ToList();
PS I've tested it and it works on your xml.
PSS Consider adding this attribute [DebuggerDisplay("{Make} - {Model}")] to your camera class to make viewing the list/array in the debugger nicer.