Is it possible to use variables like <%=person.LastName %> in XML string this way?
XElement letters = new XElement("Letters");
XElement xperson = XElement.Parse("<Table><Row><Cell><Text>
<Segment>Dear <%=person.Title%> <%=person.FirstName%> <%=person.LastName%>,
</Segment></Text></Cell></Row>...");
foreach (Person person in persons){
letters.Add(xperson)
}
If it's possible, it would be a lifesaver since I can't use XElement and XAttribute to add the nodes manually. We have multiple templates and they frequently change (edit on the fly).
If this is not doable, can you think of another way so that I can use templates for the XML?
Look like it's possible in VB
http://aspalliance.com/1534_Easy_SQL_to_XML_with_LINQ_and_Visual_Basic_2008.6
This is an exclusive VB.NET feature known as XML Literals. It was added in VB 9.0. C# does not currently support this feature. Although Microsoft has stated its intent to bridge the gap between the languages in the future, it's not clear whether this feature will make it to C# any time soon.
Your example doesn't seem clear to me. You would want to have the foreach loop before parsing the actual XML since the values are bound to the current Person object. For example, here's a VB example of XML literals:
Dim xml = <numbers>
<%= From i In Enumerable.Range(1, 5)
Select <number><%= i %></number>
%>
</numbers>
For Each e In xml.Elements()
Console.WriteLine(e.Value)
Next
The above snippet builds the following XML:
<numbers>
<number>1</number>
<number>2</number>
<number>3</number>
</numbers>
Then it writes 1, 2, 3 to the console.
If you can't modify your C# code to build the XML dynamically then perhaps you could write code that traverses the XML template and searches for predetermined fields in attributes and elements then sets the values as needed. This means you would have to iterate over all the attributes and elements in each node and have some switch statement that checks for the template field name. If you encounter a template field and you are currently iterating attributes you would set it the way attributes are set, whereas if you were iterating elements you would set it the way elements are set. This is likely not the most efficient approach but is one solution.
The simplest solution would be to use VB.NET. You can always develop it as a stand-alone project, add a reference to the dll from the C# project, pass data to the VB.NET class and have it return the final XML.
EDIT: to clarify, using VB.NET doesn't bypass the need to update the template. It allows you to specify the layout easier as an XML literal. So code still needs to be updated in VB once the layout changes. You can't load an XML template from a text file and expect the fields to be bound that way. For a truly dynamic solution that allows you to write the code once and read different templates my first suggestion is more appropriate.
Related
First I load the file in a structure
XElement xTree = XElement.Load(xml_file);
Then I create an enumerable collection of the elements.
IEnumerable<XElement> elements = xTree.Elements();
And iterate elements
foreach (XElement el in elements)
{
}
The problem is - when I fail to parse the element (a user made a typo or inserted a wrong value) - how can I report exact line in the file?
Is there any way to tie an element to its corresponding line in the file?
One way to do it (although not a proper one) –
When you find a wrong value, add an invalid char (e.g. ‘<’) to it.
So instead of: <ExeMode>Bla bla bla</ExeMode>
You’ll have: <ExeMode><Bla bla bla</ExeMode>
Then load the XML again with try / catch (System.Xml.XmlException ex).
This XmlException has LineNumber and LinePosition.
If there is a limited set of acceptable values, I believe XML Schemas have the concept of an enumerated type -- so write a schema for the file and have the parser validate against that. Assuming the parser you're using supports Schemas, which most should by now.
I haven't looked at DTDs in decades, but they may have the same kind of capability.
Otherwise, you would have to consider this semantic checking rather than syntactic checking, and that makes it your application's responsibility. If you are using a SAX parser and interpreting the data as you go, you may be able to get the line number; check your parser's features.
Otherwise the best answer I've found is to report the problem using an xpath to the affected node/token rather than a line number. You may be able to find a canned solution for that, either as a routine to run against a DOM tree or as a state machine you can run alongside your SAX code to track the path as you go.
(All the "maybe"s are because I haven't looked at what's currently available in a very long time, and because I'm trying to give an answer that is valid for all languages and parser implementations. This should still get you pointed in some useful directions.)
supposing O have these two equivalent (at least they are supposed to be) XML schemas. The actual XML will eventually be parsed by C#. I think the second way is 'more correct' since I will get attributes as actual attrbutes, instead of child elements, correct?
<?xml version="1.0" encoding="ISO-8859-1"?>
<switch>
<switch_name>switch1</switch_name>
<software_version>1</software_version>
<vendor>Cisco</vendor>
<ip_address>1.1.1.1</ipaddress>
<linecard>
<model_type>12345</model_type>
<fcport>
<slot> 1</slot>
<port> 1</port>
<speed>4</speed>
</fcport>
</linecard>
</switch>
<switch>
<switch name="switch1" version="1" vendor="Cisco" ip_address="1.1.1.1">
<linecard model="12345">
<fcport slot="1" port="1" speed="4">
</fcport>
<linecard>
</switch>
</xml>
Neither one is strictly more "correct" than the other, both will work for your example. Neither breaks any rules.
That said, I think I agree with W3Schools on this one, in that data should go inside child elements rather than attributes. Especially things like IP addresses just FEEL like data that should be a child element rather than an attribute. Attributes I typically use for metadata, such as auto generated IDs.
This is especially true if you later want to account for expansion -- for example, what if you want to associate multiple IPs? With child elements you can just add another element, but with attributes you have to come up with a new attribute name for each addition (ip1, ip2, ip3...).
There are no "right" way of representing data in XML when choosing between using elements or attributes for properties of an entity. Choose whatever works for you.
Generally elements give more freedom as you may have sub-elements eventually. I.e. if property is list of some sort representing it as comma-separated value in attribute looks very non-XML.
Side note: "XML schema" usually means different thing - structured schema for XML... what you have I'd call "representation of data in XML".
The classic article on how to choose between elements and attributes is here:
http://xml.coverpages.org/elementsAndAttrs.html
I note that at the end of the page it quotes John Cowan quoting me: "Beginnners always ask this question. Those with a little experience express their opinions passionately. Experts tell you there is no right answer'."
Currently I have a solution that builds an XML document in a number of sections and then validates the final concatenated xml against a single schema. Is it possible to use a subset of the same schema to validate each section individually?
The answer is yes in most of the cases. For a disclaimer, in theory someone could intentionally write an XML Schema that would make some of my proposals impossible, but then that would be just bad practice in XSD authoring.
For a straightforward solution, the following assumptions should be true:
A section is well formed XML; you're concatenating XmlElement nodes. E.g.:
<section-element ... attribute content>
... more content
</section-element>
Each of the sections being merged has a matching global element declaration in your XML Schema set. If you use the xsi:type attribute for any of your sections, things might get a bit tricky, but not hard to fix.
The validation would be common code, where the XmlReader would be an XmlNodeReader on the node you're concatenating. Use the XmlReaderSettings as usual...
The above would work for any XSD (you don't have a design time dependency of knowing the XSD). For anything below, the code would have to match your XSD...
If you don't have the matching global elements in the XML Schema then you have to look at the type of each matching local element declaration. If the type is global, then you can easily create, in memory, dummy elements that match your sections, of the global type (assuming a Venetian Blind authoring style).
If even the type is anonymous (more of a Russian Doll style), then you can even fake that, by creating a global element with a type that is a copy of the anonymous type - all in memory.
I have an XSD file and want to get a list of the names of all the elements in it. I don't mean stuff like <xs:sequence> and so on, just the "real stuff", that actually can appear in XML that are valid according to the XSD.
Real stuff is a bit vague
But if you just want want all elements it's just a it of Xpath.
If you want a tree, then you can't avoid sequence etc.
If you have things like xs:choice in there you have even more issues.
Then there's attributes...
From SimpleContent or ComplexType...
Might be easier to generate a 'blank' xml document from the xsd and then get what you want out of that. That's a fair chunk of code as well though. Might be one lying around you can borrow though.
If you don't actually want to do this from your code, you could use the XML Schema Definition Tool (Xsd.exe) to create source code for runtime objects.
From there you can use Xml serialization to create valid Xml samples for your given Xsd schema.
Since you're trying to code for this, I would assume you want to do this against different XML Schema files, over and over; if true, it would be then important to understand if you really have to embed this in your codebase, or if it can be used as an external tool.
If you really want to do it, most of all you need is in System.Xml.Schema package. Start with an XmlSchemaSet to load and compile your XSD files. Then using an iterator on GlobalElements, go over the global elements that can show as your root elements in XML document and traverse those (for what you need, use the PSVI properties); as someone else was mentioning, there will be types to go through, compositors, etc.; and then there's more: abstract elements (those can't show up in XML, neither references to abstract elements, instead members of substitution groups), prohibited attributes, restricted types, etc.
I've recently answered another post that may be related to your need; your posted XML Schema may look like this:
root/ship/engine/#MaxSpeed,A,1..1,True
root/ship/crew/#function,A,1..1,True
root/ship/#Name,A,1..1,True
root/ship/#class,A,1..1,True
root/ship/special_abilities/hull/#separable,A,0..1,False
root/ship/special_abilities/hull/#canCarryWesley,A,0..1,False
root/ship/special_abilities/hull/#capableOfLanding,A,0..1,False
If you want, you can deal only with the first column; the generated XPath shows only those items (elements or attributes) that have data; processing something like the above might be much easier (split the string using /, elements are all but #, etc.)
I have a big xml string that needs to be displayed as a web page. I can achieve this with xslt. Now the users will make changes to certain attributes of the xml displayed on the web page.
When they are done I need to save it back in the same xml format with the modified values.
Please guide me on what would be the best method to handle this.
using asp.net + c#
I've tried something like this in the past, and resorted to using two separate XSLT sheets, one to transform to (X)HTML, and another to transform the edited one back.
Unfortunately there isn't a 'generic' way of doing it, XSLT is a one way transform; e.g. if a stylesheet disregards an element altogether, there's obviously no way of writing an inverse XSLT that will restore it.
Another possibility is to have your XML->HTML stylesheet generate id attributes on input elements in the HTML, and give the value of that attribute a value that can easily be used as a lookup in your source XML. Then you can probably just iterate through each such element in the HTML, and lookup the related element in the source and replace the value. Or the other way round, go through each element in your source, and find the value in the HTML, either works.
Take a look at this utility:
http://www.chilkatsoft.com/refdoc/csHtmlToXmlRef.html
It might be possible to use XSLT to transform it back to HTML too, but without seeing the markup it's tough to tell.