janv. 30

By chance, I have discovered something new related to the protected keyword yesterday. I was very surprised because I had never seen such a behavior in C++ or Java. But maybe I had never tested it in the past ? Anyway, I think it's important enough to share it with you.

Private keyword

Just for reminding, a private member will be visible only in the container object (class or structure). However, you can write something like :

public class ClassWithPrivate
   private int privateMember;
   public void DoSomething(ClassWithPrivate c)
      /* The private members are also accessible on 
       * another instance, as long as you work with it
       * inside of the class */
      c.privateMember = 12;

Protected keyword

With the previous example shown, we can expect a similar behavior with the protected keyword as it is an "extended private". Indeed a protected member will be visible in the container object and also in all the derived class of this object. However, there is a limitation when working with other instances as shown below:

public class BaseClass
   protected void DoSomething() { }
public class DerivedClass : BaseClass
   public void OtherMethod()
      //The protected method of the base class is accessible on "this"
      //The protected method is accessible via another instance
      DerivedClass derived = new DerivedClass();
      /* Compilation Error:
       * Cannot access protected member 'BaseClass.DoSomething()' 
       * via a qualifier of type * 'BaseClass'; the qualifier 
       * must be of type 'DerivedClass' (or derived from it)
      BaseClass baseClass = new DerivedClass();

Experts of all language, can you tell me if you have this limitation also in your language ?

Extra question : I don't really see why we have this compilation error. Why this limitation exist ? DO you have any idea or clue ?

Tags: | | | |
janv. 27

While I was working on a training presentation in Powerpoint 2007, I have discovered a very strange and frustrating problem.

How to reproduce ?

  1. Create a simple prensentation
  2. On the first slide add an object and Insert an action
  3. Choose "Execute the program" and add a simple command line with switches like for example "cmd /K dir /P"
  4. Save the presentation and close it
  5. Open it again
  6. Select your object, and choose again "Insert action" to view the action you have added
  7. You should see "cmd \K dir \P"

All the "/" are transformed in "\"

I am now searching for a fix or patch, or an explanation to this problem (maybe I should escape the "/" but how ?)

If you have any ideas or clues, leave a comment !

Tags: |
janv. 21

I have been speaking of XSL in my latest articles, so to conclude (for now) the serie, let's see how we can call a C# (or VB.NET) function inside of an XSL file.

Let's first remember two things

  • you should be able to do whatever you want in XSL. However, as this is a functional language, you may need to forget all what you have learned with your favorites programming languages to suceed to do what you want. For examples, the fact that XSL do not allow to update the content of a variable may render things a bit trickier if you are not used to. Calling a C# function should not necessarily be used as soon as you have a problem
  • Visual Studio.NET allows you to debug an XSL file. This is very practical to validate the transformation you do. However, as soon you will call C# code from the XSL file, this won't be possible anymore. Just think before doing it ! (well... you will be able to debug, but no longer in the XSL editor)

However, despite of these two warnings, you can imagine many scenarii when this will be usefull, starting by code factorisation for example : having a single display or rendering function for C# and XSL is of course of great interest !

So let's imagine you have an XML file like this:

<?xml version="1.0" encoding="utf-8" ?>

And that you already have your formatting function in C# like (of course, this is a very basic example you could very easily do in XSL)

public class MyXslExtension
   public string FormatName(string firstName, 
                            string name)
      return name + ", " + firstName;

It's almost finished. Now you just need to use this method in an XSL file. Let's write a very basic one

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" 
<xsl:template match="/Employees">
   <xsl:for-each select="Employee">
      <xsl:value-of select="myUtils:FormatName(FirstName, 
                                               LastName)" />

As you can see we have added a new namespace in our file. What is the goal ? To map a function namespace we use in the XSL code to a .NET object we will provide. Note that the function name we use corresponds exactly to the .NET function name we have declared in our object. Note that the value of the namepsace can be whatever you want and will be used later on to do the mapping.

How to use it now ? Let's see the transformation code:

string xslPath = "XSLTFile1.xslt";
string xmlPath = "XMLFile1.xml";
string outputPath = "output.xml";
XsltArgumentList arguments = new XsltArgumentList();
arguments.AddExtensionObject("pda:MyUtils", new MyXslExtension());
using ( StreamWriter writer = new StreamWriter(outputPath) )
   XslCompiledTransform transform = new XslCompiledTransform();
   transform.Transform(xmlPath, arguments, writer);

And here it is ! When launching your code, .NET will automatically map your object to the namespace used in your XSL file.

Tags: | | | |
janv. 16

We have seen in a previous post how to use an XmlDataSource and a GridView to display a formatted view of an XML document. We have seen also how we could use XSL to help in the formatting.

As you will go on and improve your formatting, you will probably want to add a common XSL file to include in several other XSL using either an <xsl:include or an <xsl:import tag. As soon as you will do that, you will receive an exception on your page "Resolving of external URIs was prohibited." And of course, as your included / imported XSL is in the same directory, you don't really see whay the access to this file is denied.

What's happening ? In fact all included / imported resources are considered as external resources, whatever their storage location. And after investigation in the code of the XmlDataSource, you can see it has not be written to be able to resolve external resources.

It's so impossible to use an XmlDataSource with an XSL using imported or included resources.

So how can we do ? Well... Just forget the XmlDataSource in that case. So how to achieve the same things in code ?

private void BindGridViewToXmlSource()
   XmlDocument dom = new XmlDocument();
   gvPresentators.DataSource = dom.SelectNodes("YourXPathQuery");
/// <summary>
/// Return the content of the given XML path, 
/// transformed by the given Xsl file
/// </summary>
/// <param name="appRelXslPath">XSL file's app relative path</param>
/// <param name="appRelXmlPath">XML file's app relative path</param>
/// <returns></returns>
private string GetTransformedXmlData(string appRelXslPath, 
                                     string appRelativeXmlPath)
   XslCompiledTransform transform = new XslCompiledTransform();
   using ( MemoryStream stream = new MemoryStream() )
      appRelativeXmlPath = Server.MapPath(appRelativeXmlPath);
      transform.Transform(appRelativeXmlPath, null, stream);
      stream.Position = 0;
      using ( StreamReader reader = new StreamReader(stream) )
         return reader.ReadToEnd();
Tags: | | | | |
janv. 14

You all know the DateTime.ToString method I imagine. However I have had a little problem a few days ago, so let's it share with you !

You may all be aware of this behavior:

DateTime date = new DateTime(2008, 01, 14);
//To14a8 i0 14/01/2008
date.ToString("Today is dd/MM/yyyy");

Indeed in the pattern, the "d" will be interpreted as the day, "y" as the year and "s" as the seconds. So we need to protect them, enclosing the non-parasable characters using quotes. (Here enclosing the "/" is not mandatory, but I like to protect ALL my non parsable characters.

//Today is 14/01/2008
date.ToString("'Today is 'dd'/'MM'/'yyyy");

Now let's imagine your non parsable characters includes a quote.

//FormatException in both cases
date.ToString("Today, dd/MM/yyyy, I'm living in Brussels"); 
date.ToString("'Today, 'dd'/'MM'/'yyyy', I'm living in Brussels'");

You wil get a FormatException because your query includes an incorrect number of quotes (they should always work 2 by 2).  You imagine you need to protect this quote but how ? "Simply" by enclosing it with double-quotes. (Note that the exception message will be System.FormatException: Cannot find a matching quote character for the character '''.)

//Today, 14/01/2008, I'm living in Brussels
date.ToString("'Today, 'dd'/'MM'/'yyyy', I'\"'\"'m living in Brussels'");

This leads to a bit complex expression but it works !

Note that here, you find the expression '\"'\"'. The first quote (') is the closing quote of the previous text and the last one is the opening quote for the last text part. After you find two double quotes (") to protect the quote we want to write. As we are in a non-verbatim string, the double-quotes shall be protected using backslahes (\).

Tags: | | |