I have problems getting the Attributes of a XmlSchema sub element.
There is an abstactElement and a concreteElement which extends the abstractElement.
Getting the base's attributes works fine using XmlSchemaComplexType.BaseXmlSchemaType.
But getting the concreteElement's attributes using XmlSchemaComplexType.Attributes does not work.
This is my example Xml-Schema file:
<xs:schema id="XMLSchema1"
targetNamespace="http://tempuri.org/XMLSchema1.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema1.xsd"
xmlns:mstns="http://tempuri.org/XMLSchema1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name = "ConcreteElement" type="concreteElement" />
<xs:complexType name="abstractElement">
<xs:attribute name="aA1" type="xs:string" />
<xs:attribute name="aA2" type="xs:string" />
<xs:attribute name="aA3" type="xs:string" />
</xs:complexType>
<xs:complexType name="concreteElement">
<xs:complexContent>
<xs:extension base="abstractElement">
<xs:attribute name="cA1" type="xs:string"/>
<xs:attribute name="cA2" type="xs:string"/>
<xs:attribute name="cA3" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
I want to get all attributes of the ConcreteElement (cA1, cA2, cA3) and all the attributes of its base element (aA1, aA2, aA3).
My code looks like that:
public Program()
{
XmlSchema xsd =
XmlSchema.Read(
new StreamReader("/Path/To/My/Xsd/File.xsd"),
null);
var xss = new XmlSchemaSet();
xss.Add(xsd);
xss.Compile();
XmlSchemaElement xsdRoot = null;
/* Get the root element */
foreach (DictionaryEntry curEle in xsd.Elements)
{
var xse = (XmlSchemaElement)curEle.Value;
xsdRoot = xse;
break;
}
List<XmlSchemaAttribute> lsAttributes = this.GetAllAttributes(
xsdRoot.ElementSchemaType as XmlSchemaComplexType);
foreach (XmlSchemaAttribute curAtr in lsAttributes)
{
Console.WriteLine(curAtr.Name);
}
Console.ReadKey();
}
And this is my GetAllAttributes method:
private List<XmlSchemaAttribute> GetAllAttributes(
XmlSchemaComplexType comCon)
{
/* No Ancestor, no Attributes */
if (comCon == null)
{
return new List<XmlSchemaAttribute>();
}
/* Get attributs of the acestors */
List<XmlSchemaAttribute> allAttributes =
this.GetAllAttributes(
comCon.BaseXmlSchemaType as XmlSchemaComplexType);
/* Ad the attributes of the given element */
allAttributes.AddRange(comCon.Attributes.Cast<XmlSchemaAttribute>());
return allAttributes;
}
Regards,
Finally the solution is to use the Property AttributeUses, which holds all the attributes
of an element, even those which belong to the ancestors.
private List<XmlSchemaAttribute> GetAllAttributes(
XmlSchemaComplexType comCon)
{
List<XmlSchemaAttribute> allAttributes = new List<XmlSchemaAttribute>();
/* Add the attributes of the given element */
foreach (DictionaryEntry curAttriEntry in comCon.AttributeUses)
{
XmlSchemaAttribute curAttri =
curAttriEntry.Value as XmlSchemaAttribute;
if (curAttri != null)
{
allAttributes.Add(curAttri);
}
}
return allAttributes;
}
Related
I need to validate some generic sensor input. The requirement is, that the validation cannot happen in my code but with a external validator like xsd from outside the codebase to give users the ability to swap the validation logic without needing to code or recompile the application.
I know that the sensor input is only valid for one specific case and therefore would like to generate the xsd from an Instance of a class, that exists at runtime, that was user validated, to get the valid restrictions.
I tried the Idea from this question, however this only works on types and not on instances of classes.
Therefore my question: Is there a way to take a runtime instance of a C# class and convert it to an xsd that has the values of the properties as the only valid restrictions?
Update:
to clarify: What I have is a class like this:
public sealed class Sensor
{
public int Data { get; set; }
public int otherData { get; set; }
public int MoreData { get; set; }
}
the class gets instanciated somewhere (e.g. like this):
var se = new Sensor()
{
Data = 5,
otherData = 10,
MoreData = 15
};
When I now try to create an xsd using something like the following function:
var schemas = new XmlSchemas();
var exporter = new XmlSchemaExporter(schemas);
var mapping = new XmlReflectionImporter().ImportTypeMapping(typeof(Person));
exporter.ExportTypeMapping(mapping);
var schemaWriter = new StringWriter();
foreach (XmlSchema schema in schemas)
{
schema.Write(schemaWriter);
}
return schemaWriter.ToString();
I receive some xsd like this:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sensor">
<xs:complexType>
<xs:sequence>
<xs:element name="Data" type="xs:integer" />
<xs:element name="otherData" type="xs:integer" />
<xs:element name="moreData" type="xs:integer" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
However this is far from what I want to archieve. I would like to have the proper restrictions built into it (it should look something like this):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sensor">
<xs:complexType>
<xs:sequence>
<xs:element name="Data">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:enumeration value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="otherData">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:enumeration value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="moreData">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:enumeration value="15"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I could obviously go ahead load the generated file into memory, strip some attributes and change how the xsd should look like, but this feels wrong because of the following things:
By me defining Rules to how the xsd should look like I take away
flexibility that I would like to have.
This approach seems quite errorprone to me because it seems like basically a little better than direct string manipulation.
This extra code would make my already large code way complexer and harder to understand.
To sum up: I need either a library or a really clever function that can create a xsd like the one above based on the runitme info I have on the class without writing a lot of things to manipulate the xml directly to avoid errorprone or wrong assumptions about the future usage of the validation.
I took your generate schema and added details using Xml Linq. See code below
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.IO;
namespace ConsoleApplication131
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
Sensor se = new Sensor()
{
Data = 5,
otherData = 10,
MoreData = 15
};
XmlSchemas schemas = new XmlSchemas();
XmlSchemaExporter exporter = new XmlSchemaExporter(schemas);
XmlTypeMapping mapping = new XmlReflectionImporter().ImportTypeMapping(typeof(Sensor));
exporter.ExportTypeMapping(mapping);
StringWriter schemaWriter = new StringWriter();
foreach (XmlSchema schema in schemas)
{
schema.Write(schemaWriter);
}
XDocument doc = XDocument.Parse(schemaWriter.ToString());
XElement root = doc.Root;
XNamespace xs = root.GetNamespaceOfPrefix("xs");
foreach (XElement _class in doc.Descendants(xs + "complexType"))
{
List<XElement> elements = _class.Descendants(xs + "element").ToList();
if (elements.Count > 0)
{
XElement complexType = new XElement(xs + "complexType");
_class.Add(complexType);
XElement sequence = new XElement(xs + "sequence");
complexType.Add(sequence);
foreach (var prop in se.GetType().GetProperties())
{
string name = prop.Name;
string value = prop.GetValue(se, null).ToString();
XElement element = elements.Where(x => (string)x.Attribute("name") == name).FirstOrDefault();
string strType = (string)element.Attribute("type");
XElement newElement = new XElement(xs + "simpleType", new object[] {
new XElement(xs + "restriction", new object[] {
new XAttribute("base", strType),
new XElement(xs + "enumeration", new XAttribute("value", value))
})
});
sequence.Add(newElement);
}
}
}
doc.Save(FILENAME);
}
}
public sealed class Sensor
{
public int Data { get; set; }
public int otherData { get; set; }
public int MoreData { get; set; }
}
}
I have static method, which i use to validate a XML File against a XSD File. This works fine, until there is an XSD File which includes another XSD File.
Example, where i got troubles:
TYPES.XSD:
<xs:simpleType name="MY_AMOUNT">
<xs:restriction base="xs:decimal">
<xs:maxInclusive value="999999999999.99"/>
<xs:minInclusive value="-999999999999.99"/>
<xs:totalDigits value="14"/>
<xs:fractionDigits value="2"/>
</xs:restriction>
</xs:simpleType>
MAIN.XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:include schemaLocation="TYPES.xsd"/>
<xs:element name="ROOT">
<xs:complexType>
<xs:sequence>
<xs:element ref="SOMEREF1"/>
<xs:element ref="SOMEREF2"/>
<xs:element name="AMOUNT" type="MY_AMOUNT" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
VALIDATION CODE:
public static class XmlUtils
{
private static string Errors = string.Empty;
public static bool ValidateAgainstXSD(string xmlFilePath, string xsdFilePath, ref string message)
{
try
{
var settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema
| XmlSchemaValidationFlags.ProcessInlineSchema
| XmlSchemaValidationFlags.ReportValidationWarnings;
settings.Schemas.Add(null, xsdFilePath);
settings.Schemas.Compile();
settings.ValidationEventHandler += (sender, args) =>
{
if (args.Severity == XmlSeverityType.Error)
{
Errors += args.Message + "\n";
}
};
using (var reader = XmlReader.Create(xmlFilePath, settings))
{
while (reader.Read()) { }
}
message = Errors ?? string.Empty;
return string.IsNullOrEmpty(Errors);
}
catch (Exception e)
{
message = "# error validating xml file: " + e.Message;
return false;
}
}
}
Somehow it seems i have to specify the path of the included XSD File but i have no idea where.
The error occurs at settings.Schemas.Compile(); , where it says that the type "MY_AMOUNT" is not declared. I read about custom XmlResolvers but to be honest i didn't get that working.
If this is important for an answer: The xsd files are always located in the same directory!
The method is called likes this:
string msg = string.Empty;
string basedir = #"C:\Temp";
string xml = Path.Combine(basedir, "XML_FILE.xml");
string xsd = Path.Combine(basedir, "MAIN.xsd");
if (XmlUtils.ValidateAgainstXSD(xml, xsd, ref msg))
{
// do some work
}
else
{
Console.WriteLine(msg);
}
Console.ReadLine();
Any help is highly appreciated - Thank you!
UPDATE 2016-12-05:
I wrote my own XmlUrlResolver, to see what happens behind the scenes:
internal class XUrlResolver : XmlUrlResolver
{
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
return base.GetEntity(absoluteUri, role, ofObjectToReturn);
}
public override Uri ResolveUri(Uri baseUri, string relativeUri)
{
return base.ResolveUri(baseUri, relativeUri);
}
}
And the i just try to do:
XmlSchemaSet xset = new XmlSchemaSet();
xset.XmlResolver = new XUrlResolver();
xset.Add("", xsdFilePath);
xset.Compile();
What happens now (on line xset.Add):
XmlUrlResolver.ResolveUri(null,"C:\\Temp\\MAIN.XSD") --> {file:///C:/Temp/MAIN.xsd}
XmlUrlResolver.ResolveUri(null,"C:\\Temp\\MAIN.XSD") --> {file:///C:/Temp/MAIN.xsd}
XmlUrlResolver.GetEntity({file:///C:/Temp/MAIN.xsd}) --> Filestream to MAIN.xsd
XmlUrlResolver.ResolveUri({file:///C:/Temp/MAIN.xsd},"TYPES.XSD") --> {file:///C:/Temp/TYPES.xsd}
XmlUrlResolver.GetEntity({file:///C:/Temp/TYPES.xsd}) --> Filestream to TYPES.xsd
Looks good to me (except the first 2 Calls are equal!?!) - the path to TYPES.XSD is resolved as it should.
Nevertheless, xset.Compile() throws an Exception: "Type MY_AMOUNT is not declared"
And i have no idea why :/
First you need to make your xsd files valid.
Types.xsd (added schema root element and xs namespace)
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="MY_AMOUNT">
<xs:restriction base="xs:decimal">
<xs:maxInclusive value="999999999999.99"/>
<xs:minInclusive value="-999999999999.99"/>
<xs:totalDigits value="14"/>
<xs:fractionDigits value="2"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
Main.xsd (removed invalid refs).
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:include schemaLocation="TYPES.xsd"/>
<xs:element name="ROOT">
<xs:complexType>
<xs:sequence>
<xs:element name="AMOUNT" type="MY_AMOUNT" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
After that, given that both xsd files are in the same directory, your schemas will compile fine.
I ran into this very same issue.
I'm not suggesting this is the correct answer, but I got around it by setting the Environment.CurrentDirectory property to be the path where the included XSDs were located. Then it all processed just fine.
I have an object-model created by xsd.exe which has this member:
XSD:
<xs:element maxOccurs="unbounded" name="Foo">
<xs:complexType>
<xs:attribute name="bar" type="xs:string" />
<xs:anyAttribute />
</xs:complexType>
</xs:element>
Generated C# (abridged)
[XmlAnyAttribute]
public XmlAttribute[] AnyAttr { get... set... }
Deserialization is fine and this property is populated when I load an XML file like this:
<Foo bar="baz" one="one" two="three" four="ten" />
The problem is, how do I serialize? I cannot simply set fooInstance.AnyAttr = new XmlAttribute[] and then create each XmlAttribute object to go inside the AnyAttr collection because the XmlAttribute constructor is internal and can only be created by XmlDocument.CreateAttribute. However, in the current context there is no XmlDocument instance available.
So how do I create an instance of XmlAttribute suitable for use with [XmlAnyAttribute]?
It turns out that you can use a dummy instance of XmlDocument to create XML DOM components with and it works fine:
FooElement foo = new FooElement();
foo.bar = "baz";
XmlDocument dummy = new XmlDocument();
foo.AnyAttr = new XmlAttribute[] {
dummy.CreateAttribute("one", "one"),
dummy.CreateAttribute("two", "three"),
dummy.CreateAttribute("four", "ten")
};
I have the following xsd snippet:
<xs:element name="TR" type="tns:blah" />
<xs:complexType name="blah">
<xs:sequence>
<xs:element minOccurs="1" maxOccurs="1" name="Res" type="tns:Res" />
<xs:element minOccurs="0" maxOccurs="1" name="SNotifications" type="tns:ArrayOfSNotification" />
<xs:element minOccurs="0" maxOccurs="1" name="UNotifications" type="tns:ArrayOfUNotification" />
<xs:element minOccurs="0" maxOccurs="1" name="TNotifications" type="tns:ArrayOfTNotification" />
</xs:sequence>
</xs:complexType>
and I have the following xml:
<TR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://something.com/something">
<Res>
<CC>CMG</CC>
<CT>2014-07-24T14:10:03.84</CT>
<BN>994807</BN>
</Res>
<SNotifications xmlns="http://something.com/something" />
<UNotifications xmlns="http://something.com/something" />
<TNotifications xmlns="http://something.com/something" />
</TR>
I get no error validation the xml in notepad++.
but i get an error while using C#.
The error is:
exception:System.Xml.Schema.XmlSchemaValidationException: The element 'TR' in namespace 'http://something.com/something' has invalid child element 'SNotifications'. List of possible elements expected: 'SNotifications, TNotifications, UNotifications'
the C# code i use is:
xmlDocument.Schemas.Add("http://www.something.com/something", "path to xsd file");
string result = string.Empty;
xmlDocument.Validate((s, e) => result = string.Format("exception:{0}, exceptionmessage:{1}", e.Exception, e.Message));
I have already loaded the xml document.
Any help would be very much appreciated.
Thank you in advance,
gmat
Please try this.
public static bool IsValidXml(string xmlFilePath, string xsdFilePath)
{
var xdoc = XDocument.Load(xmlFilePath);
var schemas = new XmlSchemaSet();
schemas.Add(namespaceName, xsdFilePath);
Boolean result = true;
xdoc.Validate(schemas, (sender, e) =>
{
result = false;
});
return result;
}
We need to know the targetNamespace of your schema document, and the setting of elementFormDefault. Almost certainly it's one of the following:
(a) you have elementFormDefault="qualified", and the target namespace of the schema is not http://something.com/something (in which case the SNotifications element should be in the target namespace); or
(b) you don't have elementFormDefault="qualified" (in which case SNotifications should be in no namespace).
I have been tasked with finding out why a program passes an XML unit test when the attributes in the xsd portion do not match the values in the unit test. The problem is I know next to nothing about XML or xsd. I have read up on it in various places but nohing has helped me understand why the test is failing.
It seems that before I can figure out why it's not working, I need to understand what is happening in the method doing the unit testing. I think I grasp most of it, but there is a portion that I'm not sure I understand. This portion also deals with the xsd.
Here is my xsd:
public static class Constants
{
public const string Xsd = #"
<xs:schema elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"">
<xs:element name=""Datas"">
<xs:complexType>
<xs:sequence>
<xs:element name=""Data"">
<xs:attributeGroup ref=""allocData""/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:attributeGroup id=""allocData"">
<xs:attribute name=""Site"" type=""string""/>
<xs:attribute name=""MonthNum"" type=""string""/>
<xs:attribute name=""Department"" type=""string""/>
<xs:attribute name=""Numerator"" type=""float""/>
<xs:attribute name=""Data_Indicator"" type=""string""/>
<xs:attribute name=""Industry_Benchmark"" type=""int""/>
<xs:attribute name=""OSHA_Benchmark"" type=""int""/>
<!--xs:attribute name=""Comments"" type=""string""/-->
<xs:attribute name=""Executive_Comments"" type=""string""/>
<xs:attribute name=""Fleet_Executive_Comments"" type=""string""/>
</xs:attributeGroup>
</xs:schema>";
and here is the method for my unit test:
public void XMLTest()
{
List<DataResults> ListOfResults = new List<DataResults>();
DataResults r1 = new DataResults();
DataResults r2 = new DataResults();
HarvesterHandle testData = new HarvesterHandle();
r1.Site = "Springfield Site";
r1.Department = "Freak";
r1.MonthNum = "8";
r1.Numerator = 65807;
r1.Data_Indicator = "A12";
// r1.Comments = "Hello, World";
r1.Industry_Benchmark = 23;
r1.OSHA_Benchmark = 2;
r1.ExecutiveComments = "It costs HOW MUCH?";
r1.FleetExecComments = "No you can't have a new car";
r2.Site = "Joplin Site";
r2.Department = "Rock";
r2.MonthNum = "12";
r2.Numerator = 65625;
r2.Data_Indicator = "Ou812";
r2.Industry_Benchmark = 523;
r2.OSHA_Benchmark = 2456;
// r2.Comments = "GoodBye, World!";
r2.ExecutiveComments = "Cut it!";
r2.FleetExecComments = "It only has 250,000 miles";
ListOfResults.Add(r1);
ListOfResults.Add(r2);
var test = testData.XMLTest(ListOfResults);
var xmlDoc = XDocument.Parse(test.ToString());
XmlSchemaSet set = new XmlSchemaSet();
set.Add(XmlSchema.Read(XElement.Parse(Constants.Xsd).CreateReader(), (o, e) => { })); bool valid = true;
xmlDoc.Validate(set, (o, e) =>
{
valid = false;
});
Assert.IsTrue(valid);
var element = test.Descendants("Data").FirstOrDefault(x => x.Attribute("Site").Value.Equals(r1.Site));
Assert.IsNotNull(element);
Assert.AreEqual(r1.Site, element.Attribute("Site").Value);
Assert.AreEqual(r1.Department, element.Attribute("Department").Value);
Assert.AreEqual(r1.MonthNum.ToString(), element.Attribute("MonthNum").Value);
Assert.AreEqual(r1.Numerator.ToString(), element.Attribute("Numerator").Value);
Assert.AreEqual(r1.Data_Indicator, element.Attribute("Data_Indicator").Value);
Assert.AreEqual(r1.Industry_Benchmark.ToString(), element.Attribute("Industry_Benchmark").Value);
Assert.AreEqual(r1.OSHA_Benchmark.ToString(), element.Attribute("OSHA_Benchmark").Value);
// Assert.AreEqual(r1.Comments.ToString(), element.Attribute(
// "Comments").Value);
Assert.AreEqual(r1.ExecutiveComments.ToString(), element.Attribute("Executive_Comments").Value);
Assert.AreEqual(r1.FleetExecComments.ToString(), element.Attribute("Fleet_Executive_Comments").Value);
element = test.Descendants("Data").FirstOrDefault(x => x.Attribute("Site").Value.Equals(r2.Site));
Assert.IsNotNull(element);
Assert.AreEqual(r2.Site, element.Attribute("Site").Value);
Assert.AreEqual(r2.Department, element.Attribute("Department").Value);
Assert.AreEqual(r2.MonthNum.ToString(), element.Attribute("MonthNum").Value);
Assert.AreEqual(r2.Numerator.ToString(), element.Attribute("Numerator").Value);
Assert.AreEqual(r2.Data_Indicator, element.Attribute("Data_Indicator").Value);
Assert.AreEqual(r2.Industry_Benchmark.ToString(), element.Attribute("Industry_Benchmark").Value);
Assert.AreEqual(r2.OSHA_Benchmark.ToString(), element.Attribute("OSHA_Benchmark").Value);
// Assert.AreEqual(r2.Comments.ToString(), element.Attribute(
// "Comments").Value);
Assert.AreEqual(r2.ExecutiveComments.ToString(), element.Attribute(Executive_Comments").Value);
Assert.AreEqual(r2.FleetExecComments.ToString(), element.Attribute("Fleet_Executive_Comments").Value);
}
the part that appear to be dealing with the xsd is this:
XmlSchemaSet set = new XmlSchemaSet();
set.Add(XmlSchema.Read(XElement.Parse(Constants.Xsd).CreateReader(), (o, e) => { })); bool valid = true;
xmlDoc.Validate(set, (o, e) =>
{
valid = false;
});
Assert.IsTrue(valid);
The problem is if the attribute data types in the xsd do not match the actual data, the test still passes. For instance, if any of the string attributes (MonthNum, Site, etc) are changed to float, the test still passes. Also, if the .xsd element names Datas and Data are changed to something like Fred and Ethyl, the test still passes.
I am assuming that whatever the xsd portion of the code in the xml unit test method is doing, it is not checking for correct datatypes or element names
per request, here is my xml:
public const string XSLT = #"
<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"">
<xsl:output method=""text"" encoding=""us-ascii"" />
<xsl:template match=""/"">Site, MonthNum, Department, Numerator, Denominator, Data_Indicator, Industry_Benchmark, OSHA_Benchmark, <!--Comments--> Executive_Comments, Fleet_Executive_Comments,
<xsl:for-each select=""Datas/Data"">
<xsl:text>'</xsl:text>
<xsl:value-of select=""#site""/>
<xsl:text>','</xsl:text>
<xsl:value-of select=""#monthNum""/>
<xsl:text>','</xsl:text>
<xsl:value-of select=""#Department""/>
<xsl:text>','</xsl:text>
<xsl:value-of select=""#numerator""/>
<xsl:text>','</xsl:text>,
<xsl:value-of select=""Industry_Benchmark""/>
<xsl:text>'</xsl:text>,
<xsl:value-of select=""OSHA_Benchmark""/>
<xsl:text>'</xsl:text>,
<!--xsl:value-of select=""Comments""/-->
<!--xsl:text>'</xsl:text-->,
<xsl:value-of select=""Executive_Comments""/>
<xsl:text>'</xsl:text>,
<xsl:value-of select=""Fleet_Executive_Comments""/>
<xsl:text>'</xsl:text>,
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>";
}
}
edit: This is the XML generated when running the test:
<Data>
<Data Site="Springfield Site" MonthNum="8" Department="Freak" Numerator="65807" Data_Indicator="A12" Industry_Benchmark="23" OSHA_Benchmark="2" Executive_Comments="It costs HOW MUCH?" Fleet_Executive_Comments="No you can't have a new car" />
<Data Site="Joplin Site" MonthNum="12" Department="Rock" Numerator="65625" Data_Indicator="Ou812" Industry_Benchmark="523" OSHA_Benchmark="2456" Executive_Comments="Cut it!" Fleet_Executive_Comments="It only has 250,000 miles" />
</Data>
It appears that the problem was that the xsd was not correct. It was written as:
<xs:attribute name=""Site"" type=""string""/>
when it should have been written as
<xs:attribute name=""Site"" type=""xs:string""/>