API

Frågans uppbyggnad


Så här kan en fråga exempelvis se ut:

<REQUEST>
  <LOGIN authenticationkey="SomeAuthenticationKey" />
  <QUERY objecttype="SomeObjectType" limit="10">
  <FILTER>
    <EQ name="SomeDataField" value="2" />
  </FILTER>
  </QUERY>
</REQUEST>

Frågan skickas med ett POST-anrop, publiceringspunktens filändelse avgör formatet på svaret.

I URLen definieras vilken version som ska användas och ändelsen (xml eller json) anger format på det returnerade svaret.
http://api.trafikinfo.trafikverket.se/v[version]/data.[format]

Tillgängliga URLer:
http://api.trafikinfo.trafikverket.se/v1.3/data.xml
http://api.trafikinfo.trafikverket.se/v1.3/data.json
http://api.trafikinfo.trafikverket.se/v1.2/data.xml
http://api.trafikinfo.trafikverket.se/v1.2/data.json
http://api.trafikinfo.trafikverket.se/v1.1/data.xml
http://api.trafikinfo.trafikverket.se/v1.1/data.json
http://api.trafikinfo.trafikverket.se/v1/data.xml
http://api.trafikinfo.trafikverket.se/v1/data.json

<REQUEST/> omsluter frågan. Den måste innehålla <LOGIN/> och en eller flera <QUERY/>.

<LOGIN/> måste innehålla attributet authenticationkey där användarens unika nyckel anges. (Genom registrering fås tillgång till nycklar.)

<QUERY/> kan ha ett antal olika attribut:

objecttype(obligatorisk) anger datattypen som efterfrågas. Se Datamodell för tillgängliga datatyper.
idkan innehålla ett av användaren godtyckligt värde som också returneras i svaret. (Om anropet innehåller flera frågor kan id-attributet användas för att veta vilket svar som hör ihop med vilken fråga.)
includedeletedobjectsborttagna dataposter returneras om satt till true (läs mer under Förändrat data)
limitbegränsar antalet dataposter i svaret
orderbyanger på vilket eller vilka datafält sortering skall göras. Sorteringsordning anges med asc (ascending) eller desc (descending) efter datafältet (asc är default). Flera datafält separeras med komma-tecken. Exempel:
<QUERY orderby="SomeData.Name desc, SomeData.Description asc">
skiphoppar över ett visst antal dataposter i svaret (endast praktiskt användbart på statiskt data). Kan t.ex. användas vid paginering.
lastmodifiedreturnerar tidpunkten för senast uppdaterade (ModifiedTime) datapost från returnerat dataset om satt till true. Returneras under <INFO />, se Svaret

<FILTER/> måste finns under <QUERY/>, även om inga filteroperatorer anges. Det är här som det specificeras vilket data som ska returneras. Det finns ett antal olika operatorer för att bygga ihop ett filter.

<EQ/> ”Equals”, lika med
<EXISTS/> ”Exists”, värde existerar (value="true|false")
<GT/> ”Greater Than”, större än
<GTE/> ”Greater Than or Equal”, större än eller lika med
<LT/> ”Less Than”, mindre än
<LTE/> ”Less Than or Equals”, mindre än eller lika med
<NE/> ”Not Equal”, inte lika med
<LIKE/> ”Like”, testar om värdet matchar ett reguljärt uttryck. Exempelvis för att kolla om datafältet börjar med texten ”bl” <LIKE name="SomeData" value="/^bl/" />
<NOTLIKE/>”Not Like”, testar om värdet inte matchar ett reguljärt uttryck
<IN/> ”In”, testar om värdet finns med i en lista av värden
<NOTIN/> ”Not In”, testar om värdet inte finns med i en lista av värden
<WITHIN/> ”Within”, testar om värdet finns inom en geometri, läs mer under avsnitt Geo-sökningar

Operatorerna har två attribut:

nameanger namnet på datafältet som operatorn ska användas på
valuevärdet att jämföra med datafältets värde

(Operatorn <WITHIN/> kan även ha attributen shape och radius).

Operatorerna kan grupperas genom att de omsluts av följande:

<OR/>”Or” (testar att minst en av operatorerna är sann)
<AND/>”And” (testar att alla operatorer är sanna)
<ELEMENTMATCH/>
”Element match” (testar att samtliga operatorer är sanna för ett och samma element i en array)
Exempel
Låt säga att vi har följande fiktiva dataset.
{  
   User:{  
      Name:"User_1",
      Results:[  
         {  
            Product:"abc",
            Score:9
         },
         {  
            Product:"xyz",
            Score:5
         }
      ]
   }
}
{  
   User:{  
      Name:"User_2",
      Results:[  
         {  
            Product:"abc",
            Score:5
         },
         {  
            Product:"xyz",
            Score:7
         }
      ]
   }
}
Om frågan grupperar operatorerna med omslutande ELEMENTMATCH så måste samtliga kriterier vara uppfyllda för ett och samma element i arrayen.
<FILTER>
    <ELEMENTMATCH>
        <EQ name="User.Results.Product" value="abc" />
        <GT name="User.Results.Score" value="6" />
    </ELEMENTMATCH>
</FILTER>
Resultatet ger då att det enbart är ett av User-objekten som uppfyller filterkriterierna.
{  
   User:{  
      Name:"User_1",
      Results:[  
         {  
            Product:"abc",  // Uppfyller Product='abc'
            Score:9         // Uppfyller Score>6
         },
         {  
            Product:"xyz",
            Score:5
         }
      ]
   }
}
Skulle man använt AND istället för ELEMENTMATCH så räcker det med att ett kriterie var uppfyllt i ett array-element och det andra krieteriet i ett annat element.
<FILTER>
    <AND>
        <EQ name="User.Results.Product" value="abc" />
        <GT name="User.Results.Score" value="6" />
    </AND>
</FILTER>
Båda User-objekten hade då returnerats.
{  
   User:{  
      Name:"User_1",
      Results:[  
         {  
            Product:"abc",  // Uppfyller Product='abc'
            Score:9         // Uppfyller Score>6
         },
         {  
            Product:"xyz",
            Score:5
         }
      ]
   }
}
{  
   User:{  
      Name:"User_2",
      Results:[  
         {  
            Product:"abc",  // Uppfyller Product='abc'
            Score:5
         },
         {  
            Product:"xyz",
            Score:7         // Uppfyller Score>6
         }
      ]
   }
}
Dessa tre (OR, AND och ELEMENTMATCH) är också operatorer vilket innebär att de kan nästlas.

Ett exempel på ett filter:

<FILTER>
    <OR>
        <AND>
            <EQ name="User.Name" value="kalle anka" />
            <IN name="User.Category" value="a, b, c" />
        </AND>
        <GT name="User.Number" value="133" />
    </OR>
</FILTER>
Filtret i exemplet ovan anger att antingen ska User.Name vara lika med ”kalle anka” samt att User.Category ska vara något av följande värden a, b eller c, eller så ska User.Number vara större än 133.

Ofta är bara en delmängd av data intressant, då är det önskvärt att bara få det aktuella datat med i svaret. Därför är det möjligt att ange vilka datafält som ska returneras, alternativt inte returneras.

<INCLUDE/> - anger ett datafält som ska inkluderas i svaret. Datafält som inte finns definierade kommer att exkluderas i svaret. INCLUDE-elementet kan förekomma inga, en eller många gånger. Elementets innehåll definierar datafältet. Fält som det görs sortering på (d.v.s. finns angivna i QUERY-attributet orderby) kommer också att inkluderas.
Exempel:

<QUERY objecttype="SomeObjectType">
    <INCLUDE>WantedField</INCLUDE>
    <INCLUDE>WantedField2</INCLUDE>
</QUERY>

<EXCLUDE/> - anger ett datafält som ska exkluderas i svaret. Datafält som inte finns definierade kommer att inkluderas i svaret. EXCLUDE-elementet kan förekomma inga, en eller många gånger. Elementets innehåll definierar datafältet.
Exempel:

<QUERY objecttype="SomeObjectType">
    <EXCLUDE>UnwantedField</EXCLUDE>
    <EXCLUDE>UnwantedField2</EXCLUDE>
</QUERY>

<DISTINCT/> - anger ett datafält vars unika värden ska returneras. Svaret innehåller en array med unika värden av det specificerade fältet. DISTINCT-elementet kan förekomma inga eller en gång. Elementets innehåll definierar datafältet.
Exempel:

<QUERY objecttype="SomeObjectType">
    <DISTINCT>DistinctField</DISTINCT>
</QUERY>

Enbart den ena av <INCLUDE/>, <EXCLUDE/> eller <DISTINCT/> kan av naturliga skäl defineras i en <QUERY/>.

Notera att alla attributvärden i datamodellen är skiftlägeskänsliga (case sensitive).


Datum och tider

För att ange olika datum- och tidsangivelser i frågorna används följande två funktioner.
$now – nuvarande tidpunkt.
$dateadd(<timespan>) – där timespan är tiden som skall adderas till nuvarande tidpunkt.


En timespan definieras enligt d.hh:mm:ss (där ss är valfritt).

-Valfritt minus-tecken som indikerar en negativ tidsperiod.
dDagar, mellan 0 och 10675199
hhTimmar, mellan 0 och 23
mmMinuter, mellan 0 och 59
ssSekunder, mellan 0 och 59
Exempel:
Ett dygn: "1.00:00"
En timme: "0.1:00"
En minut: "0.00:01"
En sekund: "0.00:00:01"
Två dygn och 10 timmar och 15 minuter: "2.10:15"
59 minuter: "0.00:59"
60 minuter: "0.01:00"
23 timmar: "0.23:00"
24 timmar: "1.00:00"

Exempel på $dateadd-metoden som ger nuvarande tidpunkt minus 15min.
Exempel:
<GT name='AnnonseradTid' value='$dateadd(-0.00:15:00)' />

Geo-sökningar

Det finns stöd för att fråga efter objekt inom en box, polygon eller inom en radie. Operatorn som används för att ställa geo-frågor är <WITHIN>. Geo-fält är definerade som WKT, t.ex.: <SWEREF99TM>POINT(674707 6579684)</SWEREF99TM>. De fält som det är möjligt att ställa geo-frågor mot är i datamodellen markerade med . Attributet shape kan ha tre olika värden, så här kan respektive fråga se ut:

Box value="nedre vänster hörn, övre höger hörn"
<REQUEST>
    <LOGIN authenticationkey="SomeAuthenticationKey" />
    <QUERY objecttype="SomeObjectType">
    <FILTER>
     <WITHIN name="Geometry.SWEREF99TM" shape="box" value="276192 6576098, 280967 6579969"/>
    </FILTER>
  </QUERY>
</REQUEST>
Polygon value="en stängd polygon"
Notering: ange en stängd polygon, det görs genom att den första och den sista punkten har samma värde.
<REQUEST>
  <LOGIN authenticationkey="SomeAuthenticationKey" />
  <QUERY objecttype="SomeObjectType">
    <FILTER>
      <WITHIN name="Geometry.SWEREF99TM" shape="polygon"
        value="343221.595823 6473809.616383,343065.083445 6473844.341895,
               343285.880000 6473971.780000,343221.595823 6473809.616383" />
    </FILTER>
  </QUERY>
</REQUEST>
Center value="en mittpunkt", radius="radie i enhet för aktuellt referenssystem".
<REQUEST>
  <LOGIN authenticationkey="SomeAuthenticationKey" />
  <QUERY objecttype="SomeObjectType">
    <FILTER>
      <WITHIN name="Geometry.SWEREF99TM" shape="center"
                value="343207 6473960" radius="100" />
    </FILTER>
  </QUERY>
</REQUEST>
Standardenhet för SWEREF99TM är meter, men för WGS84 är det grader. Om man hellre vill ange radien i meter för WGS84-geometrier görs detta genom att suffixa radien med ett m. Exempel: <WITHIN name="Geometry.WGS84" shape="center" value="15.42 60.48" radius="500m" />. Anger man inte detta suffix ställs frågan med enheten i grader.

Förändrat data

Om ett visst data uppdateras ofta vill man också kontrollera datat ofta. Datamängden som hämtas vid varje förfrågan ska dock vara så liten som möjligt. En tillämpning som hämtar data ofta, trots att inga förändringar i datat gjorts, är felaktigt designad. Det är önskvärt att bara hämta de dataposter som har förändrats sedan förra gången samma datamängd efterfrågades. Alla dataposter innehåller datafältet ModifiedTime vilket innehåller tidpunkten då dataposten senast ändrades. Det är alltså möjligt att bara hämta de meddelanden som uppdaterats efter en viss tidpunkt. Görs en sådan hämtning så är det inte enbart förändrade dataposter som är av intresse utan även de dataposter som raderats sedan förra hämtningen. Normalt sätt returneras inte borttagna poster men genom att lägga till attributet includedeletedobjects till QUERY-elementet i frågan så kommer även borttagna dataposter att returneras i svaret. Raderade dataposter finns kvar i systemet i 24 timmar efter borttag. Borttagna dataposter innehåller datafältet Deleted=true.

Följande fråga returnerar alla dataposter av typen SomeObjectType som uppdaterats eller raderats efter 2014-01-03T09:00:00.00Z.

Fråga:

<REQUEST>
  <LOGIN authenticationkey="SomeAuthenticationKey" />
  <QUERY objecttype="SomeObjectType" includedeletedobjects="true"
          lastmodified="true">
  <FILTER>
    <GT name="ModifiedTime" value="2014-01-03T09:00:00.00Z" />
  </FILTER>
  </QUERY>
</REQUEST>

Svar:

<RESPONSE>
  <RESULT>
    <SomeObjectType>
      <Id>123</Id>
      <DataField>The data</DataField>
      <ModifiedTime>2014-01-03T09:21:27.16Z</ModifiedTime>
    </SomeObjectType>
    <SomeObjectType>
      <Id>456</Id>
      <DataField>The other data</DataField>
      <ModifiedTime>2014-01-22T09:57:56.07Z</ModifiedTime>
      <Deleted>true</Deleted>
    </SomeObjectType>
    <INFO>
      <LASTMODIFIED datetime="2014-01-22T09:57:56.07Z"></LASTMODIFIED>
    </INFO>
  </RESULT>
</RESPONSE>
Genom att attributet lastmodified var med i frågan så returnerades tidpunkten för senast uppdaterade datapost i svarets dataset. Nu har alla förändringar mottagits. Nästa gång en fråga ställs för att få dataförändringar kan frågan ändras så att det är uppdateringar eller borttag gjorda efter 2014-01-22T09:57:56.07Z som önskas.
<REQUEST>
  <LOGIN authenticationkey="SomeAuthenticationKey" />
  <QUERY objecttype="SomeObjectType" includedeletedobjects="true"
    lastmodified="true">
    <FILTER>
      <GT name="ModifiedTime" value="2014-01-22T09:57:56.07Z" />
    </FILTER>
  </QUERY>
</REQUEST>

CORS

Normalt sett så får en webbläsare av säkerhetsskäl inte göra ett XMLHttpRequest till en annan domän (cross-domain) än den som sidan ursprungligen laddades ifrån. Cross-origin resource sharing (CORS) är en mekanism för att tillåta just detta. Trafikverkets öppna API för trafikinformation har stöd för CORS. Om användarens webbläsare har stöd för CORS kommer en Origin HTTP header att bifogas anropet och webbservicen kommer i svarets header att returnera Access-Control-Allow-Origin: *.

Läs mer om CORS – http://en.wikipedia.org/wiki/Cross-origin_resource_sharing

Meddelanden

Prenumerera på denna feed