Page 1 of 1

XName in System.Xml.Linq

PostPosted: Mon Feb 14, 2011 1:12 pm
by terenced
@ref 'System.Xml'

use System.Xml.Linq

class Program
def main
showname = 'Californication'
xml = XDocument.load('http://www.tvrage.com/feeds/episode_list.php?show=[showname]')
print xml.element('show')


I get the following error running this code
TVRage.cobra(9): error: Argument 1 of method "element" expects type XName?, but the call is supplying type String.
Compilation failed - 1 error, 0 warnings
Not running due to errors above.


However, you cannot create an Xname, and in C#, you simply supply a string to the method 'Element', like so
Code: Select all
using System;
using System.Xml.Linq;

namespace TVRage
{
    class Program
    {
        static void Main(string[] args)
        {

            const string showName = "Californication";
            var xml = XDocument.Load("http://www.tvrage.com/feeds/episode_list.php?show=" + showName).Element("Show");

           Console.WriteLine(xml);
        }
    }
}


Any ideas?

Re: XName in System.Xml.Linq

PostPosted: Mon Feb 14, 2011 2:29 pm
by Charles
The .element method takes an XName:
http://msdn.microsoft.com/en-us/library/system.xml.linq.xcontainer.element.aspx

But then an examination of an XName shows that the only way you can create one is through the implicit cast operator:
http://msdn.microsoft.com/en-us/library/system.xml.linq.xname.aspx

Ug! This is the first time I've seen Microsoft rely on C#-specific features in one of their own libraries. Usually they are good about following the Common Type System (CTS) and related specs so that all languages can use them.

I also don't see why they didn't just overload the .element method to take a string, which is a common technique.

Until Cobra picks up the implicit cast operators, I do have a work around:

@ref 'System.Xml'

use System.Xml
use System.Xml.Linq


extend XDocument

def element(name as String) as XElement
return sharp'_lh_this.Element(name)'


class Program

def main
showname = 'Californication'
xml = XDocument.load('http://www.tvrage.com/feeds/episode_list.php?show=[showname]')
print xml.element('show')


Compiled with:
Code: Select all
cobra -c -native-compiler:C:\Windows\Microsoft.NET\Framework\v3.5\csc.exe xml.cobra


Let me know how it goes. Maybe we can cook up a more extensive example and post it in the wiki or the samples section.

Re: XName in System.Xml.Linq

PostPosted: Mon Feb 14, 2011 4:36 pm
by terenced
Oh cool!
I also tired
@ref 'System.Xml'

use System.Xml.Linq

class Program
def main
showname = 'Californication'
xml = XDocument.load('http://www.tvrage.com/feeds/episode_list.php?show=[showname]')
print xml.element('show' to XName)

and it also worked.

However, I tired to be a bit more sneaky and did the following
@ref 'System.Xml'

use System.Xml
use System.Xml.Linq


extend XContainer

def element(name as String) as XElement?
return .element(name to XName)


class Program

def main
showname = 'Californication'
xml = XDocument.load('http://www.tvrage.com/feeds/episode_list.php?show=[showname]')
print xml.element('Show').element('name').value

I used XContainer instead of XDocument, this way XElement would also have the extension method. The casting seems a bit simpler than inbedding C# code ;)
I am working on a little app that will make use of my Linq-fu, so we can definitely get few examples for the wiki.
I also created a mini bundle for TextMate, nothing fancy. Would you like it as well?

Re: XName in System.Xml.Linq

PostPosted: Mon Feb 14, 2011 5:27 pm
by terenced
Strange, if I add another extension, I get some funny errors
@ref 'System.Xml'

use System.Xml
use System.Xml.Linq


extend XContainer

def element(name as String) as XElement?
return .element(name to XName)

def attribute(name as String) as XAttribute?
return .attribute(name to XName)


class Program

def main
showname = 'Californication'
xml = XDocument.load('http://www.tvrage.com/feeds/episode_list.php?show=[showname]').element('Show')
print xml.element('name').value
for seasons in xml.element("Episodelist").elements
if seasons.attribute('no') <> nil
print '\tSeasons: [int.parse(seasons.attribute("no").value)]'


I get the following errors:
xml.cobra(13): error: Argument 1 of method "attribute" expects type String?, but the call is supplying type XName.
xml.cobra(23): error: Argument 1 of method "attribute" expects type XName?, but the call is supplying type String.
xml.cobra(24): error: Argument 1 of method "attribute" expects type XName?, but the call is supplying type String.
Compilation failed - 3 errors, 0 warnings
Not running due to errors above.

Now, I did get something similar when I created the 1st extension for element, but it went away when I upgraded Mono.

Re: XName in System.Xml.Linq

PostPosted: Mon Feb 14, 2011 9:07 pm
by Charles
In the MSDN docs, I don't see an .attribute on XContainer. So then the compiler thinks you're calling the only .attribute it knows about--the one you're declaring. And that makes for a type error since it expects a String, not an XName.

I don't see it on XDocument either, but I do see it on XElement. So I added an "extend XElement" before "def attribute" and now the code compiles.

With all these XClasses, I'm expecting to see XMen. :-)

Re: XName in System.Xml.Linq

PostPosted: Mon Feb 14, 2011 10:00 pm
by Charles
And yes, please post your TextMate bundle in a new topic called TextMate. Thanks.