Syndication

News

     

Archives

Miscelaneous

Programming

January 2004 - Posts

Note: this entry has moved.

I'm the one to blame for breaking the site. Sorry guys! Inadvertently, I placed an XML element on the title, and it broke everything. What's more, I couldn't even delete the post afterwards because the Admin UI was broken too. I had to dump the Admin page to disk, fix the problem by hand, reload it and finally delete the post. Sorry!!!!
Posted by Daniel Cazzulino | 5 comment(s)
Filed under:

Note: this entry has moved.

For those showing XML in a post, you surely know how annoying it is to be forced to convert all the tags to the corresponding escaped sequence in order to get it properly rendered. That is, change the < and > characters. There's a cool element, <xmp>, which allows arbitrary markup and tells the browser to show it as-is, without any processing. It's a kind of <pre> but better because you don't have to escape reserved characters.

Even though it was made obsolete by the HTML 4 specification, it remains a very useful element. In fact, despite the suggestion to use the <pre> element, there's no other element that offers the possibility to show markup without escaping it. What's more, both Gecko-based browsers (Netscape, Mozilla and Firebird) and IE properly render the element content untouched. Open this page in both and you'll see the XML at the very beginning properly displayed, even when it has not been escaped.

The strange thing is that even when RssBandit uses an embedded IE for post display, it's modifying the contents of the <xmp> and removing my formatting (tabs, whitespaces and line breaks), and that's why you would see the post rather ugly. Even more strange, it's doing so ONLY for XML content, not for the C# code I embedd... :S

Posted by Daniel Cazzulino | 9 comment(s)
Filed under:

Note: this entry has moved.

Consider the following XML:

<Person> <FirstName>Daniel</FirstName> <LastName>Cazzulino</LastName> </Person>

We can use the XmlSerializer to reconstruct an instance of the following class from it:

public class Person { public string FirstName { get { return _first; } set { _first = value; } } string _first; public string LastName { get { return _last; } set { _last = value; } } string _last; }

So far so good. Now, if we use the XmlSerializer to serialize an instance of Person to Xml, you'd be "surprised" to get the following XML (declaration aside):

<Person xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <FirstName>Daniel</FirstName> <LastName>Cazzulino</LastName> </Person>

Now, those namespace declaration weren't there in the original XML! The only way to get rid of them is to create a custom XmlTextWriter to use with the XmlSerializer:

public class NonXsiTextWriter : XmlTextWriter { public NonXsiTextWriter( TextWriter w ) : base( w ) {} public NonXsiTextWriter( Stream w, Encoding encoding ) : base( w, encoding ) {} public NonXsiTextWriter( string filename, Encoding encoding ) : base( filename, encoding ) {} bool _skip = false; public override void WriteStartAttribute( string prefix, string localName, string ns ) { if ( prefix == "xmlns" && ( localName == "xsd" || localName == "xsi" ) ) // Omits XSD and XSI declarations. { _skip = true; return; } base.WriteStartAttribute( prefix, localName, ns ); } public override void WriteString( string text ) { if ( _skip ) return; base.WriteString( text ); } public override void WriteEndAttribute() { if ( _skip ) { // Reset the flag, so we keep writing. _skip = false; return; } base.WriteEndAttribute(); } }

The skip flag works because everytime an attribute is being written, the three methods are called in a sequence: WriteStartAttribute, WriteString and WriteEndAttribute. Now, our writer will omit the xsd and xsi namespace declarations and preserve full fidelity with regards to the original XML. We just need to pass our writer to the XmlSerializer:

StringWriter sw = new StringWriter(); ser.Serialize( new NonXsiTextWriter( sw ), person ); Console.WriteLine( sw.ToString() );

Update: there's another way to achieve this namespace declarations omissions, as pointed by Jiho Han. But we will still need the specialized writer below.

Let's go a bit further and say we have an Employee class that inherits from Person:

public class Employee : Person { public string EmployeeID { get { return _id; } set { _id = value; } } string _id; }

This is only natural in most OO apps. Now, serializing an instance of Employee will result in the following XML (using our NonXsiTextWriter):

<Employee> <FirstName>Daniel</FirstName> <LastName>Cazzulino</LastName> <EmployeeID>1234</EmployeeID> </Employee>

Well, Houston, we have a problem. Even when Employee inherits from Person, the XmlSerializer will no longer be able to deserialize this XML into a Person object, because it expects a root <Person> element. So, what we can do is make the Employee class expect/render the root element of a Person object:

[XmlRoot("Person")] public class Employee : Person

The XmlSerializer will be able to deserialize the following XML into a Person or an Employee, depending on the Type passed to its ctor:

<Person> <FirstName>Daniel</FirstName> <LastName>Cazzulino</LastName> <EmployeeID>1234</EmployeeID> </Person>

So far so good. Now, if we have an XML containing a bunch of <Person> elements, let's say <People>, and its corresponding class: 

public class People { [XmlElement("Person", typeof(Person))] public Person[] AllPeople { get { return _people; } set { _people = value; } } Person[] _people; }

The XmlSerializer will be perfectly capable of deserializing the following XML:

<People> <Person> <FirstName>Daniel</FirstName> <LastName>Cazzulino</LastName> </Person> <Person> <FirstName>Victor</FirstName> <LastName>Garcia Aprea</LastName> </Person> </People>

And it will be able to generate exactly the same document from the following object:

People p = new People(); p.AllPeople = new Person[] { new Person("Daniel", "Cazzulino"), new Person("Victor", "Garcia Aprea") };

Now, being an Employee a Person, we may want to populate the People class with them too, let's say VGA becomes and Employee while I remain an independent person:

People p = new People(); p.AllPeople = new Person[] { new Person("Daniel", "Cazzulino"), new Employee("Victor", "Garcia Aprea", "9999") };

The XmlSerializer will no longer know how to serialize the People type unless we tell it to expect an Employee too. The exception will say something like "Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.". Adding these attributes to the base class, pointing to derived classes is not a good idea. Furthermore, new derived classes may appear that we may not know ahead of time. So, instead of adding those attributes, we can just pass the additional types to the XmlSerializer ctor:

XmlSerializer ser = new XmlSerializer( typeof( People ), new Type[] { typeof( Employee ) } );

Cool. Now the serializer will be able to serialize a People object containing a mix of Person and Employee instances. However, the XML will not look like what you expected:

<People> <Person> <FirstName>Daniel</FirstName> <LastName>Cazzulino</LastName> </Person> <Person d2p1:type="Employee" xmlns:d2p1="http://www.w3.org/2001/XMLSchema-instance"> <FirstName>Victor</FirstName> <LastName>Garcia Aprea</LastName> <EmployeeID>9999</EmployeeID> </Person> </People>

What's more, we have effectively broken the deserialization of regular People now, in the sense that a piece of code that only knows how to deal with Person objects, wishing to deserialize the XML with an XmlSerializer constructed without the Employee extra type parameter will fail with the following error:

"The specified type was not recognized: name='Employee', namespace='', at <Person xmlns=''>"

So, even though the XML containing the extra data for an Employee could be successuly deserialized into a Person, as we saw above, the type="Employee" attribute is breaking it. Note that the namespace prefix is "d2p1" instead of the regular "xsi" because  I used the NonXsiTextWriter, which prevented the namespace to be mapped to "xsi" and the root element. Therefore, a "random" new prefix is being created. 
What we need is a way to completely avoid emitting the xsi:type attribute. We can further modify the NonXsiTextWriter to skip all "xsi" attributes it finds as they're being written:

public override void WriteStartAttribute( string prefix, string localName, string ns ) { if ( ( prefix == "xmlns" && (localName == "xsd" || localName == "xsi")) || // Omits XSD and XSI declarations. ns == XmlSchema.InstanceNamespace ) // Omits all XSI attributes. { _skip = true; return; } base.WriteStartAttribute( prefix, localName, ns ); }

With the new check for ns == XmlSchema.InstanceNamespace we're effectively bypassing the attribute writing. Now, the part of the program that works against Person instances can simply deserialize the People class without knowing there is Employee data also, or that there is an Employee class altogether. It will simply be ignored by the XmlSerializer. This is specially useful in configuration scenarios, where there may be extensible points like providers that need to be handled generically by your custom configuration handler, but need to be instanciated and initialized with custom configuration. Your generic provider class could simply specify the Type as an attribute, and the custom handler would deserialize the entire node into the Provider-derived class:

object IConfigurationSectionHandler.Create( object parent, object configContext, XmlNode section) { XmlSerializer ser = new XmlSerializer(typeof(MyConfigurationWithProviders)); MyConfigurationWithProviders cfg = (MyConfigurationWithProviders) ser.Deserialize( new XmlNodeReader( section ) ); // Iterate providers. XmlNodeList providers = section.SelectNodes("Provider"); foreach (XmlNode p in providers) { Type t = Type.GetType( p.Attributes["Type"].Value ); XmlSerializer ps = new XmlSerializer( t ); object instance = ps.Deserialize( new XmlNodeReader ( p ) ); // We have a derived type fully initialized!! } }

Our Provider class would be all too simple:

public class Provider { [XmlAttribute] public string Type { get { return _type; } set { _type = value; } } string _type; }

Afterwards, a derived provider, for example a DbStorageProvider, would be:

[XmlRoot("Provider")] public class DbStorageProvider : Provider { public int Timeout { get { return _timeout; } set { _timeout = value; } } string _timeout; }

I'm sure you appreciate the power and flexibility of this approach. You no longer need to worry about "parsing" the XmlNode in search for your properties, load them, etc. You can just rely on the generic XmlSerializer-based configuration handler above. The configuration for the provider can be as complex as you like, and it integrates well with the base functionality of the handler:

<MyCoolSection> <SomeConfig>...</SomeConfig> <Providers> <Provider Type="MyCoolApp.DbStorageProvider, MyCoolApp"> <Timeout>25</Timeout> <Audit>true</Audit> </Provider> </Providers> </MyCoolSection>

But you not only gain loading ease of use, you can also modify your provider instance and serialize back to the configuration file, preserving the format thanks to the NonXsiTextWriter we wrote. Now you can build a flexible configuration API based on the XmlSerializer features, letting developers programmatically configure your application. For example, let's say some admin interface allows adding new providers. The code could do something like the following:

AnotherProvider ap = new AnotherProvider(); // Set all properties // Pass to configuration API MyConfig cfg = (MyConfig) ConfigurationSection.GetSection( "MyCoolSection" ); cfg.Providers.Add( ap ); // Save passing the extra types array to use with the XmlSerializer. MyConfigManager.Save( cfg, new Type[] { typeof (AnotherProvider) } );

I believe this is a far more straightforward way of handling extensible configuration. Instead of implementing a sort of IProvider.Init(XmlNode config) feature, providers only need to care about the serialization format they want. I've seen that in many places in ASP.NET 2, providers receive some kind of NameValueCollection. This is clearly a step in the wrong direction. Complex configuration simply can't be handled by key-value pairs (or it's too ugly/cumbersome to do so). Imaging a provider with lots of attributes because that's the only config. supported... ugh..

Posted by Daniel Cazzulino | 13 comment(s)
Filed under: ,

Note: this entry has moved.

I noticed (like many others) that IBM was missing from WS-Eventing. If the reasons initially given by IBM were right, I could be disapointed, but I could understand that they want to sell MQ Series instead of WS-Eventing. However, it appears that they have come up with a competing specification that aims at doing mostly the same thing!!! WS-Notification was released almost at the same time!!!
So what the hell is going on?!?! Can't they just agree on ONE set of WS-* specs? I'm afraid the WS-* specs will become a nightmare to master (not to mention interop). Looks like everyone wants to be THE ONE that writes the specs...
Posted by Daniel Cazzulino
Filed under:

Note: this entry has moved.

Now that I'm an MVP, I wanted to know how many colleagues I have around the globe, as well as how many XML ones. From the official MVP list (does not contain recently announced MVPs), and the spanish-specifc list:

MVPs around the world1858
XML MVPS around the worldUpdated: 13
Latam MVPs44
Argentina MVPsUpdated: 17
XML MVPs in Latamnone!
XML MVPs in Argentinanone!

The more amazed I am with the award :o)

Posted by Daniel Cazzulino | 2 comment(s)
Filed under: ,

Note: this entry has moved.

I would like to thank ( //the-ones-that-nominated-me[@MS or @otherwise] ) for the MVP award MS gave me on the XML area. It's certainly heartwarming to see one's efforts recognized. I've just read DonXML is onboard too. That's great.
I will do my best to keep up with my community contributions during this year. Lots of projects are shaping, both in my mind and through my hands ;).
Updated: Oleg has been awarded too. Cool!
Posted by Daniel Cazzulino | 10 comment(s)
Filed under:

Note: this entry has moved.

Every now and then I make the big mistake of clicking that damn Print button at the right on MSDN articles, only to realize that most of the time the text gets cut to the right on the paper. I have already complained about the pain of printing on the web (on badly designed sites, i.e. NOT like XML.com or CNET).
Well, IMO, MSDN wins all prizes for bad print-friendliness. Poping-up that f**g window is just SO annoying! And thanks God the site is for DEVELOPERS! (that's the "D" in "MSDN", or is it "Microsoft Droid Network?!?!)
One more time, Mozilla (Firebird actually) doesn't let me down, and at least MSDN pages aren't so "intelligent" as to ruin my browsing experience, and at least I get a view of what it's f**g trying to print.

For the curious, I was trying to print Keith Pijanowski article. For the spanish-taking, and who know that the first part of his last name doesn't mean "yuppie", poor guy. Somebody please tell him, as he even shortens his name KeithPij.org, which pronounced fast sounds really bad around here... (Argentina)

Updated: What's more, if you want to get rid of the floating panel and the bottom voting panel, just use Firebird EditCSS extension as I explained, and just add the following styles to the bottom of it:
.MNPPart { display: none; }
#frmRatings { display: none; }
#msviFooter { display: none; }
Enjoy.
Posted by Daniel Cazzulino | 3 comment(s)
Filed under:

Note: this entry has moved.

DonXML is proposing extensions to OCL to express business rules that can be used at code-gen time and at run-time.
He mentions my Schematron implementation called Schematron.NET, which allows many business rules to be expressed simply in terms of standard XPath expressions. I believe such an XPath-based language is good enough to express almost every business rule.

Udi Dahan commented as an example, a rule "only a bank manager can authorize a loan above X" which he said couldn't be expressed with Don's idea. It could, indeed, with something along these lines (XPath-like):

<assert test="sec:principal-role('BankManager') and po:Loan/@Amount < 1000">
  Only a BankManager can place a loan of more than $1000.
</assert>

Note that XPath extensibility allows for more domain-specific extensions to be active, which can even check against databases, etc. For example, something like this:

<assert test="crm:customer-id(po:CustomerId)" />

in this case, the application would map the "crm" prefix to the business objects that contain the logic, and register the "customer-id" extension function to ensure the Id is a valid one. This way, you can change business rules based on a (well documented) set of extensions, and you can let managers handle them, instead of programmers.
These schemas are easy enough for an advanced user to edit.
In Schematron.NET, I'm implementing quite a few extensions, including XSLT-specific ones, and adding the full EXSLT for .NET implemented by Dare Obasanjo. It's not impossible to think about a set of domain-specific standard specs (like EXSLT itself) that would aid in business rules expression.

Posted by Daniel Cazzulino | 2 comment(s)
Filed under: ,

Note: this entry has moved.

In a previous post, I proposed an implementation of a simple method to make the first letter of an identifier uppercase, to get a pseudo PascalCase from an xml name. I've found that a better and more consistent way is to reuse the method used by the XmlSerializer to build the code identifiers, which is System.Xml.Serialization.CodeIdentifier.MakePascal(string identifier)

The class also exposes MakeValid and MakeCamel methods, which are usefull too. MakeValid is automatically called by the other two.

The pascal casing implementation is the following (reflectoring - that is, using Reflector):

public static string MakePascal(string identifier)
{ 
  char ch1;
  identifier = CodeIdentifier.MakeValid(identifier);
  if (identifier.Length <= 2)
  {
    return identifier.ToUpper(CultureInfo.InvariantCulture); 
  }
  if (char.IsLower(identifier.Chars[0]))
  {
    ch1 = char.ToUpper(identifier.Chars[0], CultureInfo.InvariantCulture);
    return string.Concat(ch1.ToString(), identifier.Substring(1)); 
  }
  return identifier; 
}

Using the ToCharArray() approach looks to me like a little more efficient string handling. The code above, near the end concatenates two strings, building a third one which is returned. If it used something like the following, it would save those two temporary strings:

  if (char.IsLower(identifier.Chars[0]))
  {
    Char[] letters = identifier.ToCharArray();
    letters[0] = Char.ToUpper( letters[0] );
    return new string( letters );
  }
}

By the way, it looks like readers' concerns with regards to I18N are non-issues, as the .NET class uses the same approach I showed, basically making a unicode Char uppercase. Finally, note that this is not actually PascalCase, but only FirstLetterUpperCase, although such a method name wouldn't be cool at all...

Posted by Daniel Cazzulino | 1 comment(s)
Filed under: ,

Note: this entry has moved.

Have you noticed that even if the W3C WXS spec allows annotations in the root <xs:schema> element, the corresponding .NET class XmlSchema does not inherit from XmlSchemaAnnotated as almost every other element does?
Looks like an "inheritance bug" to me ;)

[Update]: Dare corrected my mistake by clarifying that there can be multiple annotations, unlike the other SchemaAnnotated-derived classes. However, I couldn't find any XmlSchema member exposing such information. Therefore, the only workaround seems to be to keep an XPathDocument for the schema too.

Posted by Daniel Cazzulino | 2 comment(s)
Filed under:
More Posts Next page »