<commit_before>---
layout: tutorial
title: "Decoding nodes as primitive types"
section: tutorial
sort: 1
---
The simplest possible use of kantan.xpath is to extract primitive types from XML documents.

In order to show how that works, we'll first need some sample XML data, which we'll get from this project's resources:

```tut:silent
val rawData: java.net.URL = getClass.getResource("/simple.xml")
```

This is what we're working with:

```tut
scala.io.Source.fromURL(rawData).mkString
```

We'll then need to import kantan.xpath's syntax, which will let us evaluate XPath expressions directly on something
that can be turned into an XML document:

```tut:silent
import kantan.xpath.implicits._
```

This allows us to write the following code, which will attempt to extract the `id` field of any `element` node as an
`Int`:

```tut
rawData.evalXPath[Int](xp"//element/@id")
```


There are a few things worth pointing out here. First, the return type: you might expect an `Int`, since this is what
you requested from [`evalXPath`], but we got an [`XPathResult[Int]`][`XPathResult`] instead. An [`XPathResult`] is 
either a failure if something went wrong (the XPath expression is not valid, the `id` field is not a valid `Int`....) or
a success otherwise. This mechanism ensures that [`evalXPath`] is safe: no exception will be thrown and break the flow 
of your code. For example:

```tut
// Note that we're trying to parse ints as URLs.
rawData.evalXPath[java.net.URL](xp"//element/@id")
```

In some cases, however, we don't really care for runtime safety and are fine with our program crashing at the first
error. This is what the [`unsafeEvalXPath`] method was designed for:  

```tut
rawData.unsafeEvalXPath[Int](xp"//element/@id")
```


Another point of interest is that the sample XML file contained multiple `element` nodes, but we only got the `id`
attribute of the first one. This is due to the type parameter we passed to [`evalXPath`]: by requesting a non-collection
type, we told kantan.xpath that we only wanted the first result. We could get them all by requesting a 
[`List[Int]`][`List`], for example:


```tut
rawData.evalXPath[List[Int]](xp"//element/@id")
```

Any type constructor that has a [`CanBuildFrom`] instance could have been used instead of [`List`] - that's essentially
all collections. By the same token, any primitive time could have been used instead of `Int`. For example:

```tut
rawData.evalXPath[Vector[Boolean]](xp"//element/@enabled")
```
<commit_msg>Documentation.<commit_after>---
layout: tutorial
title: "Decoding nodes as primitive types"
section: tutorial
sort: 1
---
The simplest possible use of kantan.xpath is to extract primitive types from XML documents.

In order to show how that works, we'll first need some sample XML data, which we'll get from this project's resources:

```tut:silent
val rawData: java.net.URL = getClass.getResource("/simple.xml")
```

This is what we're working with:

```tut
scala.io.Source.fromURL(rawData).mkString
```

We'll then need to import kantan.xpath's syntax, which will let us evaluate XPath expressions directly on something
that can be turned into an XML document:

```tut:silent
import kantan.xpath.implicits._
```

This allows us to write the following code, which will attempt to extract the `id` field of any `element` node as an
`Int`:

```tut
rawData.evalXPath[Int](xp"//element/@id")
```


There are a few things worth pointing out here. First, the return type: you might expect an `Int`, since this is what
you requested from [`evalXPath`], but we got an [`XPathResult[Int]`][`XPathResult`] instead. An [`XPathResult`] is 
either a failure if something went wrong (the XPath expression is not valid, the `id` field is not a valid `Int`....) or
a success otherwise. This mechanism ensures that [`evalXPath`] is safe: no exception will be thrown and break the flow 
of your code. For example:

```tut
rawData.evalXPath[java.net.URL](xp"//element/@id")
```

In some cases, however, we don't really care for runtime safety and are fine with our program crashing at the first
error. This is what the [`unsafeEvalXPath`] method was designed for:  

```tut
rawData.unsafeEvalXPath[Int](xp"//element/@id")
```


Another point of interest is that the sample XML file contained multiple `element` nodes, but we only got the `id`
attribute of the first one. This is due to the type parameter we passed to [`evalXPath`]: by requesting a non-collection
type, we told kantan.xpath that we only wanted the first result. We could get them all by requesting a 
[`List[Int]`][`List`], for example:


```tut
rawData.evalXPath[List[Int]](xp"//element/@id")
```

Any type constructor that has a [`CanBuildFrom`] instance could have been used instead of [`List`] - that's essentially
all collections. By the same token, any primitive time could have been used instead of `Int`. For example:

```tut
rawData.evalXPath[Vector[Boolean]](xp"//element/@enabled")
```

{'fraction_non_alphanumeric': 0.10870445344129555, 'fraction_numerical': 0.0004048582995951417, 'mean_word_length': 4.7121387283236995, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6424890', 'n_tokens_mistral': 1522, 'n_tokens_neox': 1433, 'n_words': 671}