Posts Tagged ‘rättsinformation’

Två svar på tal

torsdag, juni 2nd, 2005

Den första: I förrgår skrev jag om att det var omöjligt att hitta EG-domstolens dom i apoteksmonopolmålet. Nu kan man hitta den här. Jag har dock inte läst den än (den är låååång, och jag har en tenta i övermorgon…)

Jag försökte också hitta de två hovrättsdomar som handlade om spritimportförbudets vara eller inte vara. Ingen av de bägge finns på Domstolsväsendets rättsinformation, men genom Juridik Direkt (som man kommer åt som juridikstudent) hittade jag vad som verkar vara de relevanta målen: B194-99 i Hovrätten över Skåne och Blekinge, där de tilltalade frias för varusmuggling (där var det dock inte fråga om internethandel), och B1260-02 i Hovrätten för Västra Sverige, där TR’s domslut fastställs (som är att spriten i fråga förverkas).

Hovrättens domar finns i de flesta fall inte på nätet. Vissa fall, som har allmänt intresse men som inte överklagas till HD, publiceras i Rättsfall från Hovrätterna i anonymiserad form, och dyker då (gissningsvis?) upp även hos Domstolsväsendets rättsinformation. Men så inte dessa två domar.

Den andra: Förra veckan klagade jag över att det är så svårt att hitta bland internationella normkällor, men nyligen såg jag att Wikipedia-spinoffen Wikisource håller på att bygga upp en samling konstitutionella dokument, och det finns väl ingen anledning till att den inte kan byggas ut med även andra normkällor (så länge de inte är upphovsrättsskyddade, vilket väl tillhör ovanligheterna). Här är EU-konstitutionen, exempelvis.

Apoteksmonopolet, spritimport och om att gå till källan

tisdag, maj 31st, 2005

Som programmerare var en av de viktigaste sakerna jag lärde mig att, när jag behövde veta hur någonting egentligen låg till, så gick jag till källan. I mitt fall källkoden. Det är dumt och ett tidsslöseri att sitta och spekulera i vad det ena eller andra ordet i dokumentationen av ett API kan betyda, om man kan gå till källkoden och se vad som egentligen händer.

Att läsa källkod är svårt. De flesta som vill bli programmerare kan lär sig skriva källkod ganska fort, men konsten att läsa den kan ta många år. Under tiden sitter de och gissar hur saker fungerar utifrån funktionsnamn, hörsägen och osammanhängande dokumentation.

Vilket är litegrann som juridiken i samhället fungerar. Visst kan man få en bild av hur saker och ting ligger till genom att läsa tidningar, se på nyheterna och lyssna på mer eller mindre insatta debattörer, men ska man veta vad som egentligen gäller måste man gå till källan — dvs lagtext, förarbeten, rättsfall och andra primärkällor.

Problemet är att de flesta massmedier och fria debattörer inte direkt uppmuntrar någon att gå till källan.

Idag är två frågor uppe på tapeten där man skulle ha varit betjänt av att kunna gå till källan. Den lilla nyheten är fortsättningen på en debatt som startades av Anitra Steen i lördags kring huruvida det är lagligt att beställa sprit från utlandet. Idag går Ola Wiklund i svaromål.

Olas argument känns mer solida än Anitras (framförallt hänvisningen till legalitetsprincipen), men i centrum för debatten står två hovrättsdomar. Anitra skriver “Hovrätten för Västra Sverige har i ett mål om distanshandel dömt enligt förbudet i den svenska alkohollagen. Hovrätten över Skåne och Blekinge har dömt tvärtom.” medans Ola skriver “Att statens agerande strider mot EG-rätten har redan slagits fast i två hovrättsbeslut och av EU-kommissionen”.

De här två utsagorna går, om vi antar att de hänvisar till samma två hovrättsdomar, inte rikigt ihop. Vilket inte nödvändigtvis är så konstigt. Många mer komplicerade domskäl låter sig inte sammanfattas i ett enkelt “lagligt” eller “olagligt”, och om man försöker förenkla frågorna så att de får plats på DN Debatt missar man viktiga detaljer. Man kan välja sida efter vem man tycker verkar trovärdigast, men vill man kunna bilda sig en egen uppfattning måste man själv läsa domsluten. Men hur ska man kunna göra det när ingen av debattörerna talar om vilka beslut det är frågan om?

Vi som vill bilda vår egen uppfattning uppmuntras inte att gå till källan (även om Anitra får pluspoäng för att hon åtminstone sade vilka domstolar det var frågan om). Som för att understryka det hela ligger databasen hos Domstolsväsendets rättsinformation nere idag, så jag kan inte ens försöka leta rätt på domsluten.

Den stora nyheten för dagen är dock EG-domstolens beslut om apoteksmonopolet. Inte helt förvånande utropar båda sidorna sig till vinnare, eftersom domslutet är svårtolkat. Här kan man återigen välja sida efter vem man tycker verkar trovärdigast, eller så kan man läsa domslutet själv.

Men, precis som med Domstolsväsendets rättsinformation är Europadomstolens sökformulär nere idag. Viss heder åt DN som har åtminstone kopior av en summering av domen och ett förslag til avgörande.

Man kan observera att varken curia.eu.int eller www.rattsinfosok.dom.se verkar vara några speciellt prioriterade servrar. I ett samhälle där bara ett fåtal riktigt insnöade människor är intresserade av att gå till källan är det kanske inte så konstigt.

Vissa invänder kanske att de flesta faktiskt varken har tid eller möjlighet att sätta sig in i det juridiska språket och att de är bättre betjänta av att insatta människor gör det åt dem. Men det är ett argument på samma nivå som att öppen källkod är meningslöst eftersom de flesta inte är intresserade av att läsa någon källkod.

Det är bra om källkoden till de program man använder är tillgänglig. Även om inte just du använder den, så ökar det den allmänna kunskapen, och uppmuntrar ett aktivt deltagande. På samma sätt är det är bra om källorna till de regler som styr samhället är tillgängliga. Det ökar den allmänna kunskapen, och uppmuntrar ett aktivt deltagande.

Att hitta bland internationella normkällor

onsdag, maj 25th, 2005

Jag sitter just nu och läser in mig på området barnrätt, framförallt i boken “Barnrättens grunder“, och slås av att det är ett område som i hög grad är präglat av internationell rätt.

För att förstå barnrätt bör man förstå barnkonventionen, Europakonventionen, och ett antal andra konventioner, fördrag och andra normkällor. “Normkälla” är, för att prata programmerarlingo, en superklass till subklasser som “Lag”, “Fördrag”, “Konvention”, “Kollektivavtal”, “Branschsedvänja” och andra mer eller mindre välspecificerade entiteter som talar om Vad Som Gäller<tm>.

Internationell rätt och folkrätt är ett intressant område. Det tar lång tid att överhuvudtaget förhandla fram dokument som barnkonventionen, och sen tar den långa processen med att få så många stater som möjligt att ratificiera så mycket som möjligt vid. Om man ska utreda ett rättsförhållande behöver man inte bara hitta konventionen i fråga, man måste reda ut vilka länder som ratificierat, när de gjorde det, vilka eventuella förbehåll de gjort, och om de senare avträtt från konventionen. I värsta fall måste man ta hänsyn till vilka språk dokumentet officiellt finns i, och om det kan finnas en semantisk skillnad mellan dem. Finner man att någon av de inblandade staterna brutit mot ett åtagande vidtar sen frågan om det finns några sanktioner som kan användas.

Svensk lagstiftning framstår helt plötsligt som trivialt enkel i jämförelse. Bara en sån sak som att alla författningar har en unik identifierare(SFS-numret) gör letandet mycket enklare.

I Sverige har vi ett system för hur vi namnger och identifierar legala dokument. EU har ett annat (eller flera stycken), FN har ett tredje, WIPO har ett fjärde, ILO har ett femte… Samma normkälla kan gå under flera namn (EUCD, INFOSOC eller 2001/29/EG, Romfördraget eller EG-fördraget) och namnen är ofta ganska intetsägande — förväxla för allt i världen inte Romfördraget (grundläggande regler för Europeiska Gemenskapen) med EU’s Romkonvention (lagvalsregler inom Europeiska Gemenskapen) eller WIPO’s Romkonvention (upphovsrättsregler).

De dokument som dessa organisationer ger ut kan dessutom införlivas med svensk rätt på tre olika sätt:

  • Fördragskonform tolkning — Riksdagen godkänner ratificierandet på grund av att innehållet anses stå i överensstämmelse med svensk lag. Gäller för exempelvis barnkonventionen
  • Transformation — svenska lagar skrivs eller ändras på så sätt att de uppfyller kraven i konventionen eller direktivet. Gäller för alla EG-direktiv och exempelvis “Europarådets konvention om erkännande och verkställighet rörande vårdnad av barn samt om återställande av vård av barn”
  • Inkorporering — dokumentet lyfts in (översatt) som bilaga eller liknande till en svensk författning. Gäller för exempelvis Europakonventionen om de mänskliga rättigheterna (SFS 1994:1501, men konventionstexten finns inte med där) eller CISC

Allt det här sammantaget gör att det blir riktigt jobbigt att hitta källtexten till de här normkällorna. Vilket i sin tur gör det jobbigt att förstå texter som har fullt med referenser till dem. Det vore smutt med en webtjänst som samlade ihop källtexter, på de officiella språken, med ev. länkar till officiella URL:er, ordnat efter område och/eller utgivande organ. Bara att leta rätt på länkarna till den här texten tog en timme, och då hittade jag inte ens de svenska versionerna.

Hmm. Jag känner ett behov av ytterligare en framtida feature på lagen.nu

Lagtext och förändringar över tiden

tisdag, maj 10th, 2005

LawMeme har ett fint citat i foten på sina sidor: “Leges humanae nascuntur, vivunt, moriuntur” (”människans lagar föds, lever, och dör”). När jag byggde lagen.nu tänkte jag väldigt lite på det faktum att en lagsamling förändras över tiden. Ett halvår senare börjar detta ställa till problem.

Det första problemet är att mina rutiner för att upptäcka att lagar slutat gälla inte var perfekta. Det finns två sätt som en lag kan upphävas; dels kan det utfärdas en ändringsförfattning som bara säger att en annan lag ska upphövas, dels kan det utfärdas en grundförfattning som i sina ikraftträdandebestämmelser anger att en annan lag ska upphövas.

Min uppdateringskod klarade bara av det första fallet, vilket fick till följd att en hel massa lagar som borde ha markerats som upphävda inte blev det. Inte bra. “Markerad som upphävd” betyder i det här fallet att en fet röd ruta uppmärksammar läsaren på att författningen är upphävd, och genom vilken annan författning det kom att bli så. Sidan metataggas också så att Google och andra sökmotorer inte indexerar den.

Nåväl, det är fixat nu (även om resultatet inte ligger ute än), men i samband med det har ett annat problem blivit uppenbart: Många lagar som ska upphävas i framtiden (säg, den 1:a januari 2006) är redan nu markerade som upphävda. Detta för att rutinen som ritar den röda rutan bara kollar OM det finns ett upphävd-datum, inte om detta datum har inträffat än.

Så för att lösa detta måste datumet tolkas och tas hänsyn till, dessutom måste jag se till att bygga om sidorna så fort som möjligt efter att datumet passerats. Det är rätt lätt gjort, i en perfekt framtid kommer sidorna regenereras en gång om dygnet ändå.

Men datumdilemmorna tar inte slut där! När en lagändring är på G förs den nya lydelsen av en ändrad paragraf in i SFST (den databas jag hämtar allt från), och placeras bredvid den gamla lydelsen, med en liten markör om när den gamla slutar gälla och den nya börjar:

10 § /Upphör att gälla U:2005-05-01/ Undersökningstillstånd beträffande olja, gasformiga kolväten eller diamant skall förenas med de villkor som behövs för att skydda allmänna intressen eller enskild rätt. 10 § /Träder i kraft I:2005-05-01/ Undersökningstillstånd skall förenas med de villkor som behövs för att skydda allmänna intressen eller enskild rätt samt med villkor om att tillståndshavaren skall ställa säkerhet för ersättning enligt 7 kap. 1 §. Lag (2005:161).

Det där är ju rätt fult, speciellt när det rör större textmassor. Ibland gäller det hela kapitel, och då är det lätt att man tappar bort sig och lusläser paragrafer som inte alls gäller för tillfället. Jag skulle vilja plocka bort den version av paragrafen som inte gäller just nu för tillfället. Det är ganska riskabelt, med tanke på att en bugg lätt kan leda till att man plockar bort en paragraf som ska gälla. Tänk hur annorlunda världen skulle bli om 36 § AvtL plötsligt försvann.

Med ett rejält regressionstestramverk och mycket manuell koll kanske jag vågar mig på ett sådant tillvägagångssätt. Men även då stöter man på sådana här markörer:

/Träder i kraft I: den dag regeringen bestämmer/

Tack för den! Det är dags att ta ett steg tillbaka och fundera kring vad målet är med de här övningarna överhuvudtaget. Idag presenterar lagen.nu samma i grund och botten information som finns i SFST, möjligtvis med lite snyggare formattering och hyperlänkning. Jag skulle vilja att lagen.nu i första hand alltid presenterade landets författningar som de är just nu i aktuell stund. På längre sikt skulle jag vilja bygga en sorts “tidsmaskin”, så att man kan se vilka lagar som gällde ett visst givet tillfälle. Detta är speciellt viktigt om man, säg, ska utreda ett visst skattetekniskt handlande som pågick under ett halvår tre år bak i tiden; då är det av yttersta vikt att veta vilka regler som gällde vid varje givet tillfälle.

Idag har jag ungefär ett halvårs sparad “laghistoria”, och en sådan här tidsmaskin skulle alltså högst kunna gå bakåt ett halvår. Oavsett vad skulle det kräva en hel del smart programmering, mycket testande, och en hel del redaktionellt arbete (för att exempelvis ta reda på när regeringen ikraftträtt vissa paragrafer).

Sen ska man veta att vissa bestämmelser om exempelvis bodelning vid äktenskapsskillnad eller uppsägningstid är beroende av hur lagen såg ut när äktenskapet eller anställningen inleddes. Det är alltså riktigt riktigt svårt att ta reda på vad som gäller. Man måste även lusläsa eventuella övergångsbestämmelser. Men sånt är, åtminstone för tillfället, överkurs. Något manuellt harvande ska vi lämna åt yrkesjuristerna.

Part 5: Finding and formatting inline law references

lördag, december 18th, 2004

(Earlier posts: 1, 2, 3, 4)

The second part of the convert-things-to-xml approach deals with finding inline references to other paragraphs in the law text. I’ve written about it in part in this blog post, but to recap:

Swedish law text contains lots and lots of internal and external references to other sections. These references have a semi-standardized format, but they are clearly meant to be parsed by humans, not machines.

The simplest case is a single reference to a single section (example from 4 § Försäkringsrörelselagen (1982:713)):

    Vid ändring av en bolagsordning eller av en beviljad koncession
    gäller 3 § i tillämpliga delar.
  

Here, the string ‘3 §’ signifies a reference to the third section in the current section of the current law. If we can identify and mark that reference up, we can make the ‘3 §’ into a hyperlink leading to the definition of section 3. You know, the stuff hyperlinking was designed for. Currently, this gets transformed into the following XML (how the XML gets transformed into clickable HTML is the subject of a later article):

    Vid ändring av en bolagsordning eller av en beviljad koncession
    gäller <link section=”3″>3 §</link> i tillämpliga delar.
  

For cases like that, the transformation is trivial, and could be done with regexps or just simple string matching. But for cases like this (Patentbesvärsrätten 96-837):

    14 § 1 st. 6) och 6 § varumärkeslagen (1960:644)
  

or better yet, this (49 a § URL, my personal favourite):

    Bestämmelserna i 2 § andra och tredje styckena, 3, 7--9 och 11 §§,
    12 § första stycket, 13, 15, 16, 18--20 och 23 §§, 24 § första
    stycket, 25--26 b, 26 d -- 26 f, 26 i -- 28, 31--38, 41, 42 och
    50--52 §§ skall tillämpas på bilder som avses i denna paragraf.
  

things get way more complicated. Enter EBNF-grammar-based parsing with the dynamic duo that is SimpleParse and mxTextTools. Also, the book Text Processing in Python by David Mertz should be mentioned, as it helped me in the right direction when I realized regexes weren’t going to cut it.

My previous post describes the actual EBNF grammar and how SimpleParse is used to build a parse tree from it, so you might want to read that too.

However, that is really only half of the problem. After having a tree of parsed tokens, that might (for a somewhat complicated scenario) look like the following:

refs': '14 § 1 st. 6) och 6 § varumärkes|lagen (1960:644)'
    'ExternalRefs': '14 § 1 st. 6) och 6 § varumärkes|lagen (1960:644)'
        'MultipleGenericRefs': '14 § 1 st. 6) och 6 §'
            'GenericRefs': '14 § 1 st. 6)'
                'GenericRef': '14 § 1 st. 6)'
                    'SectionPieceRef': '14 § 1 st. 6)'
                        'SectionRef': '14 §'
                            'SectionRefID': '14'
                                'number': '14'
                            'Whitespace': ' '
                        'Whitespace': ' '
                        'PieceRef': '1 st. 6)'
                            'PieceRefID': '1'
                                'ordinal': '1'
                            'Whitespace': ' '
                            'PieceOrPieces': 'st.'
                            'Whitespace': ' '
                            'ItemRef': '6)'
                                'ItemRefID': '6'
                                    'number': '6'
                                'RightParen': ')'
            'WAndOrW': ' och '
                'Whitespace': ' '
                'AndOr': 'och'
                    'And': 'och'
                'Whitespace': ' '
            'GenericRefs': '6 §'
                'GenericRef': '6 §'
                    'SectionRef': '6 §'
                        'SectionRefID': '6'
                            'number': '6'
                        'Whitespace': ' '
        'Whitespace': ' '
        'ExternalLawRef': 'varumärkes|lagen (1960:644)'
            'NamedExternalLawRef': 'varumärkes|lagen (1960:644)'
                'word': 'varumärkes'
                'Pipe': '|'
                'LawSynonyms': 'lagen'
                'Whitespace': ' '
                'LawRef': '(1960:644)'
                    'LeftParen': '('
                    'LawRefID': '1960:644'
                        'digit': '1'
                        'digit': '9'
                        'digit': '6'
                        'digit': '0'
                        'Colon': ':'
                        'digit': '6'
                        'digit': '4'
                        'digit': '4'
                    'RightParen': ')'
  

, how do we turn it into the following XML?

    <link law="1960:644" section="14" piece="1" item="6">
      14 § 1 st. 6)
    </link>
    och 
    <link law="1960:644" section="6">
      6 §
    </link>
    varumärkes|lagen (
    <link law="1960:644">
      1960:644
    </link>
    )
  

Turns out this is a problem that can be solved in a rather generic manner with a small amount of planning and a little recursiveness. Basically, all tokens that end in ‘Ref‘ should generally end up formatted as a <link>. All tokens underneath such tokens that ends in ‘RefID‘ are used to find the attributes for these tags. Start at the root, then recurse depth-first over all child nodes until done. Sometimes there are notes that end in Ref underneath other nodes also ending in Ref, in those cases it’s the top node that is turned into a <link> tag

Of course, there are exceptions and things to be aware of. Two of these are illustrated in the above example. To correctly insert the law reference (the SFS id ‘1960:644′) for tag to be produced from the MultipleGenericRefs token ‘14 § 1 st. 6) och 6 §‘, we have to plan ahead, when dealing with the parent node (ExternalRefs). The formatter has built-in knowledge of the special handling needed, and, when encountering a ExternalRefs node, finds the ExternalLawRef node child, stores the underlying LawRefID value, and later picks this value up when formatting the tags for the two GenericRef tokens.

To make this looping and recursing easier, I build a OO wrapper around the array-based parse tree that mxTextTools return. This was the subject of another post.

Note also that the ExternalLawRef token did not result in a <link> tag, but the underlying LawRefID token did. This was a consious decision (I thought it looked better that way), and was implemented by creating a number of extra subroutines in the formatter. Basically, the main function acts as a generic dispatcher, by looping over all subtokens in a tree, and for each token, checks if there’s a corresponding format_tokenname() function. If so, call that, otherwise call a generic formatter (which may, recursivly, make use of the generic dispatcher). The code is pretty simple, but is indicative of how neat stuff like this can be done in dynamic langugages:

        try:
            formatter = getattr(self,"format_"+part.tag)
            res = formatter(part)
        except AttributeError:
            res = self.format_tokentree(part)
  

The other wierd thing is that ‘|’ sign in the term ‘varumärkes|lagen‘. This is swedish for ‘the trademark law’, but since we like to write words together, this creates an interesting challenge for creating the EBNF gramar. Basically, I cannot find a way to match a word that ends in a specific suffix, such as ‘lagen‘. The resulting parser is always ‘greedy’, so there seem to be no way of matching these words without matching all words. So, to fix this, I preprocess the text before putting it through the parser, using normal python regular expressions, which can be non-greedy, to put in that ‘|’ sign, which solves the problem. Then, after retrieving the string from the tag formatter, I remove those signs.

One particular satisfying thing of the problem described in this post is that how well it lends itselfs to automated regression testing. Any new feature can easily be specified in a test case before coding begins, and after it’s done, it’s easy to verify that nothing that previously worked has been broken. More on regression testing in a later post.

Part 4: Converting stuff to XML

torsdag, december 16th, 2004

(If you missed part 1-3, they are here, here and here)

If you look at a sample law text as they are presented in SFST, they are 100% plaintext. In order to convert them to semantically sensible XML, we must look for patterns in the plaintext, to identify things like headlines, start of sections and references.

I did this with a two-part approach. First; I break down the text into it’s individual paragraphs and determine what each paragraph is. This analysis operate on a ‘block level’ — either a block of text is a headline, part of an ordered list, the start of a section etc, or it isn’t. A block can’t be half headline and half ordered list.

Secondly, if the paragraph can contain references to other parts of the law (or parts of other laws, for that matter), I analyze the text in greater detail to find and resolve these references. This step operates on a ‘token’ or character level – a block of text can contain zero, one or many of these references.

The first part is fairly easy, at least conceptually. I wrote a bunch of functions like is_chapter(p), is_section(p), is_headline(p), where each individual function just performs a simple test. These are then used from a simple loop that uses a bunch of local variables to keep track of what kind of structures we’ve encountered so far – a so-called state machine.

These functions started out as very simple regexp-based inline expressions, but as I encountered more and more exceptions to my simple rules, their complexity grew. The body of current swedish law is over 250 years old, and consistency has not been the law makers forte. Here’s an example of how to recognize the start of a section:

    re_SectionId       = re.compile(r'^(\d+ ?\w?) §[ \.]') # used for both match+sub
    re_SectionIdOld    = re.compile(r'^§ (\d+ ?\w?).')     # as used in eg 1810:0926

    def is_section(self,p):
        section_id = self.section_id(p)
        if section_id == None:
            return False
        if section_id == '1':
            if self.verbose: print "is_section: The section numbering's restarting"
            return True
        # now, if this sectionid is less than last section id, the
        # section is probably just a reference and not really the
        # start of a new section. One example of that is
        # /1991:1469#K1P7S1. We use util.numsort to get section id's
        # like "26 g" correct.
        a = [self.current_section,section_id]
        
        if a == util.numsort(a):
            # ok, the sort order's still the same, which means the potential new section has a larger ID
            if self.verbose: print "is_section: '%s' looks like the start of the section, and it probably is (%s < %s)" % (
                p[:30], self.current_section, section_id)
            return True
        else:
            if self.verbose: print "is_section: Even though '%s' looks like the start of the section, the numbering's wrong (%s > %s)" % (
                p[:30], self.current_section, section_id)
            return False
    
    def section_id(self,p):
        match = self.re_SectionId.match(p)
        if match:
            return match.group(1).replace(" ","")
        else:
            match = self.re_SectionIdOld.match(p)
            if match:
                return match.group(1).replace(" ","")
            else:
                return None
  

So, the start of a section looks like ‘<number> [letter] §’, unless it looks like ‘§ <number> [letter]’, and as long as the section id is larger than the previous section id, unless it’s restarting at 1, and also taking into account that section ids can contain an optional letter (like ‘26 g’). Simple as that.

For example, below is the start of the swedish copyright law (which has, during development, been my foremost test case). Now, if you don’t read Swedish, just know that the first paragraph signifies the start of chapter one (”1 Kap.”), the second the start of a section(”1 §”), and then there are three items in an ordered list, and finally a plain ol’ paragraph of text. (By the way, for my swedish readers: The swedish legal term ‘paragraf’ is NOT the same as the english typographical term ‘paragraph’, but rather translates into ’section’. When the english word ‘paragraph’ is used, it is in the same sense as the swedish word ’stycke’)

1 Kap. Upphovsrättens föremål och innehåll

1 § Den som har skapat ett litterärt eller konstnärligt verk har
upphovsrätt till verket oavsett om det är

1. skönlitterär eller beskrivande framställning i skrift eller tal,

2. datorprogram,

[…other items in the ordered list omitted for brevity…]

Till litterära verk hänförs kartor, samt även andra i teckning eller
grafik eller i plastisk form utförda verk av beskrivande art.

[…more things omitted for brevity…]

2 § Upphovsrätt innefattar, med de inskränkningar som nedan stadgas,
uteslutande rätt att förfoga över verket genom att framställa exemplar
därav och genom att göra det tillgängligt för allmänheten, i
ursprungligt eller ändrat skick, i översättning eller bearbetning, i
annan litteratur- eller konstart eller i annan teknik.
  

So, to make sense of this, the following state transitions are done:

  • For the first paragraph, is_chapter() will return True, so we transition to the in_chapter state. This will emit a <chapter id=”1″> tag to the result, along with the text.
  • For the second paragraph, is_section() will return True, transitioning us to the in_section stage as well. It’s important to realize that these states are mostly independent; we can be in a chapter w/o being in a section, and vice versa (some laws have only sections, no chapters). This transition will of course emit a a <chapter id=”1″> tag to the result.
  • For the third paragraph, is_ordered_list() will return True, transitioning us to the in_ordered_list state, and emitting <ol><li>1. skönlitterär eller […]</li> to the result. A couple of things to note about this:
    • These tags may look like HTML tags, but they’re not. They do, in this case, share the same semantics, though.
    • A HTML ordered list (<ol>) keeps track of it’s numbering, and any user-agent should add the numbers to the displayed result. Since this is not HTML, we don’t do that, and instead keep the number that was in the original text. Mostly because we’re not sure that no ordered list in the entire body of swedish law doesn’t contain sequence gaps or things like ‘26 g’.
  • For the fourth, is_ordered_list() will again return true, but now we’re already in the in_ordered_list state, so we don’t emit the initial <ol> tag.
  • Then we omit some boring junk, and then we encounter a normal paragraph. There is no function named is_ordinary_paragraph(), this is just infered from the fact that none of our other test matched. Now, the start of a normal paragraph is implicit evidence that our ordered list must have ended, and so the code to transition into in_normal_paragraph state checks to see if we’re in the in_ordered_list state, and if so, emits the trailing </ol>. After that, the normal paragraph gets emitted as <p>Till litterära verk […]</p>.
  • Similarly, when we encounter the start of a new section (”2 § Upphovsrätt innefattar“), we transition out of any ordered lists we might be in, out of the in_section state, emit </section>, and then transition into the same state again.

The largest part of this high-level parsing was to find all the different structures and discover the implicit state transitions that needed to take place. One interesting problem is determining wheter a given paragraph is a headline or just a really short ordinary paragraph. Well, it turns out that a headline never ends with a period, and a ordinary paragraph always does. Except for headlines that end in “m.m.” (swedish for “etc.”). And ordinary paragraph that end with “,”, “och” or “samt”. But a headline is always followed by a section, so we can peek ahead to see if the next paragraph matches is_section(). Except for those cases where a headline is followed by ANOTHER headline, which is then followed by a section…

A lot of work, and there are still a lot of places where we break (for example, things like definition lists, nested ordered lists, and tables, are not yet supported). Furthermore, tweaking to satisfy one case can easily make other cases break. I will return to this problem in the part about regression testing.

Some other things: As you may have guessed by the usage of the term “emit”, I construct the XML by hand in a single pass. This means that I write XML data straight to a file, without using DOM or anything similar. It was just easier to start out that way. I am thinking of overhauling the state machine mechanism a bit, and I might take a DOM approach then.

Some other parts of the code that constructs XML documents (like the code that handle court verdicts) use DOM, and it works pretty fine, with one small exception: It does not play nice with xml fragments in string form. I have a separate class to find law references in text (to be covered in deeper detail in the next post), and the interface of that class is a plain string one: it returns strings like “<link law=”1960:644″ piece=”2″ section=”1″>1 § 2 st.</link> varumärkeslagen“. Since there isn’t any method on individual element objects like ele.ParseAndAppendMixedContent(), I first have to create a ‘fake’ XML document and transform it into a node tree with parseString (from minidom):

    s = '<?xml version="1.0" encoding="iso-8859-1"?><%s>%s</%s>' % (
                        element, string_containing_mixed_xml_content, element)
    fragment = parseString(s)
    subele = fragment.documentElement
    ele.appendChild(subele)
  

Another drawback of writing XML the raw way is that there is no guarantee that your output will be valid. Special care is taken to escape things like < and &, and to ensure the document is well-formed, it’s also run through HTML Tidy (with the options -q -n -xml –indent auto –char-encoding latin1), which, despite it’s name, is an excellent tool to tidy up XML as well.

Part 2: Fetching stuff from the web

tisdag, december 14th, 2004

(A continuation of the series started in this post)

Now, the first thing that needs to be done is to actually get the text of the laws from the web. Before that can be done, a list of available laws must be fetched. In Swedish law, most laws have nice ID’s known as “SFS-nummer”, usually on the form “yyyy:nnn”, where yyyy is the year it was issued, and nnn is incremented for each law passed that year. Some of the older laws don’t strictly follow this convention, and can have ID’s like “1736:0123 2″ or “1844:50 s.2″.

To get a list of all laws passed between two years, one can use this form from Regeringskansliets Rättsdatabaser. It uses the normal GET method, and so it’s quite easy to construct a URL that will return all laws between, say, 1600 and 1850 (linebreaks inserted for readability):

http://62.95.69.15/cgi-bin/thw?${HTML}=sfsr_lst&
${OOHTML}=sfsr_dok&${SNHTML}=sfsr_err&${MAXPAGE}=26&
${BASE}=SFSR&${FORD}=FIND&ÅR=FRÅN+1600&
ÅR=TILL+1850

To fetch this, I used urllib2. Now for a little aside rant: Why are there two urllibs in the standard distribution? I understand that basic urllib has a simple interface and urllib2 a more complex, but would it be so hard to design a single module that lets you do simple things easy, and progress onto hard things? In the Perl world, you can start with LWP::Simple and then go on to more advanced stuff, but with python it’s either simple urllib requests with practially no control at all, or urllib2 with it’s way-too-complex system of chained handlers. I will return to this rant in a little bit, but for now let’s have some useful content. This is the code used to fetch stuff:

url = "http://62.95.69.15/...ÅR=FRÅN+%s&ÅR=TILL+%s" % (1600,1850)
sock = urllib.urlopen(url)
html = sock.read()
  

So, as long as your needs are simple, like just wanting to do a simple GET or POST, urllib and/or urllib2 will work. However, I encountered a more complex scenario when I wanted to download court verdicts from Domstolsväsendets rättsinformation: This is a web app that relies on HTTP posts, HTTP redirects, session tracking cookies, frames, javascript links and is, in general, incredibly fragile. The slightest “error” in what you send and the server answers with a “500 Server Error: java.lang.NullPointerException

The first problem was that the application requires cookie support, which urllib2 doesn’t have (as it doesn’t have any concept of state between requests). At first I thought I could fix the cookie support by reading and setting headers, the way it was done back in the day when men were men and knew the cookie spec by heart. Turns out the web service sets a cookie when you issue a search request, but the answer from the search request is a HTTP redirect. To get the resulting list of matches, you need to present that same cookie that was set.

Now, let’s continue the rant: urllib2 blindly follows the redirect, giving us no chance to set the Cookie header. From the documentation, it appears that it should be possible to override this behaviour by subclassing HTTPRedirectHandler and passing the instance to build_opener, which creates a chain of instances of BaseHandler or a subclassed class. Reading the documentation for urllib2 makes me think that someones OO/design patterns fetish was not kept properly in check. Anyway, I could not get that to work.

Another thing that bugs me about urllib2 is that is has no support for implementing Robots Exclusion Standard (RES) support. Right now, neither Regeringskansliets databaser or Domstolsväsendets rättsinformation has a /robots.txt, but if they put one in tomorrow I think I should respect it.

I did briefly use ClientCookie, which is an add-on module for urllib2 that provides automatic cookie support, and it did solve my first problem. Although I did not try it, it can also be used to provide RES support, proper Referer setting, and some other goodies. It seems that at least the cookie handling functionality of ClientCookie has been folded into urllib2 in Python 2.4, which is a good thing.

However, some time after I first got some code to work with the site, they changed something around and made it even more fragile. No matter what I did, I couldn’t get the site to respond with anything other than a “500 Server Error“, even though I checked the client-server communication when using IE (with the excellent Fiddler utility), and replicated the behaviour down to the exact header level.

So, I remembered that Erik had told me about the virtues of webscraping using IE and COM automation. Since I’m only running the code on windows machines, giving up platform independence wasn’t that big a deal, and the rich COM support in both Python and IE made it quite easy (after installing pywin32 for COM support). Here’s the basic code:

      from win32com.client import Dispatch
      ie = Dispatch("InternetExplorer.Application")
      ie.Visible = 1
      ie.Navigate("http://www.rattsinfosok.dom.se/lagrummet/index.jsp")
      while ie.Busy: sleep(1)
      ie.Document.frames(1).Document.forms(0).all.item("txtAvgDatumFran").value = startdate.strftime("%Y-%m-%d")
      ie.Document.frames(1).Document.forms(0).all.item("txtAvgDatumTill").value = "%s-12-31" % year
      ie.Document.frames(1).Document.forms(0).all.item("slctDomstol").value = "ALLAMYND"
      ie.Document.frames(1).Document.forms(0).all.item("buttonSok").click()
      while ie.Busy: sleep(1)
      html = ie.Document.frames(1).Document.body.outerHTML.encode('iso-8859-1')
  

With such a javascript- and browser behaviour dependent web app such as this, you can really save yourself a whole lot of trouble if your code can use that web browser instead of trying to emulate that web browser. For one thing, behaviour implemented in javascript (OnClick-handlers and the like) is reproduced correctly without any extra work.

Well, that’s all for now about fetching stuff from the web. Next installment will center around making sense of what we’ve just fetched, i.e. parsing HTML and stuff.

Legal document standards, part 2

fredag, december 3rd, 2004

Rasmus blogs about open standards and open access for law texts, a topic of great interest to me as of lately (or ‘obsession’, apparently :-). We both agree that there are too little of that, and that the much-heralded open governement could do better in this area.

Anyway, I came across an interesting report, a summary from a conference held about two years ago. It featured various people working with legal information systems, both in the government and private companies, sharing their views on standardisation of document formats and systems. There are views from the people behind Rixlex, Infodata and Notisum, amongst others, but also an interesting view into the state of legal information standards in Norway. They seem to be way ahead of Sweden in this area.

The general consensus seemed to be “standardization is good, and we should do it”, but with no real commitments or timeplans. Maybe there has been developments that I don’t know about since then. This was, after all, two years ago.

Meanwhile, if you want to do interesting stuff today with the body of swedish law, such as making a WAP version or performing graph analysis of all references contained in the 7500+ texts, just download my completely non-{standardized,documented} XML version and go nuts!

There are now at least three document standards, or efforts to create such, for marking up law texts and other legal doucments on my radar: uscfrag (mentioned earlier), used by Cornell University for marking up US Code, LegalXML which seems to be US-centric, and LEXML, which appears to be more EU-centric. It even has it’s own Sourceforge page!

I had no idea so much was going on in so many committees when I started working on the XMLization of swedish law. In a way I’m glad that I didn’t, since I probably would have focused too much on adhereing to these emerging standards and less time to, you know, getting things done. Or worse, just waited for them to actually finish.

The US Code in XML

måndag, november 22nd, 2004

From this groklaw post, I learned that Cornell University has transformed the entire US Code to XML. Now, I’m not well versed in US Law, but this is basically all federal laws currently in effect in USA, right? This is a very cool project. I’ve started to look around, but seemingly as I only barely can navigate around in swedish law texts, there’s a lot of exploring to be done. If you want to just read the laws, this seems to be a good place to start.

(By the way, could any US law scholar tell me whether the US constitution is a part of USC, or if it’s a separate collection of documents? I cannot seem to find them, only references to it.)

As I’ve been working on a project with similar goals for the last few months, I’m particularly interested in the XML format looks. I’ve only started to scratch the surface, but initially it seems to be somewhat more presentation-oriented (and way more complex) than the simple structures I use.

Maybe this format could be used anyway, or at least a XSLT transformation to transfer from Lagen.nu-ML (not yet documented) to uscfrag.

Law is not code

måndag, september 13th, 2004

I have not yet read Lawrence Lessig’s “Code and other laws of cyberspace“, but I like its catchphrase, “Code is Law”. Sadly, the reverse do not hold, particularly not in the real world.

As a programmer, it’s natural for me to view any legal text, be it a law, an agreement or something else, as a set of definitions, conditions and other instructions, similar to a computer program. Most of the time, these instructions are badly written; they do not strive for simplicity, they do not cover corner cases, and for many inputs the outcome is impossible to determine without resorting to case law. In computer terms, way too much checking is done at runtime (when laws are applied) instead of compile time (when they are written).

There’s an interesting article up on Kuro5hin which argues along the same lines, and how the awful quality of most laws makes for a very opaque society, where only legally trained people with a lot of time on their hands can fully understand the rules.

The author draws paralells between the way laws are written and computer programs are constructed, and suggests that the law making process should be “open sourced”; I think the process is already about as open as it can be. What’s lacking is good engineering: the will to strive for clear and simple designs.

Computer programmers realized the need for a structured approach to programming almost as soon as programming was invented. This was needed to be able to construct and maintain large programs. There is, no doubt, a lot of structured thinking in law as well, with its 3000+ year history, but somewhere along the way it seems that clear and unambigious writing fell off the list of things to prioritize.

Of course, my reasoning is a classic example of someone, new to a field, thinking they can apply all lessons learned in another field. I might have more insightful commentary after a few years of law school.