Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This is just an extension to the answer by <a href="https://stackoverflow.com/users/621719">EarlGray</a>. See the explanation of <code>&gt;&gt;.</code> and <code>&gt;.</code>! After asking the question I recognized that I need to walk through the tree in a special and deterministic way. So this is the solution I’m using for my specific problem. For the case someone else tries to accomplish the same thing, I wanted to share the example code.</p> <p>Let’s say we want to extract the text of the first <code>&lt;a&gt;</code> and the second <code>&lt;b&gt;</code>. Not all <code>&lt;a&gt;</code> elements have at least two <code>&lt;b&gt;</code>s, so the code of <a href="https://stackoverflow.com/users/621719">EarlGray</a> would bail out, because you can’t use the <code>(!!)</code> function (empty list!).</p> <p>Have a look at the function <code>single</code> in <a href="http://hackage.haskell.org/packages/archive/hxt/9.3.1.1/doc/html/src/Control-Arrow-ArrowList.html#single" rel="nofollow noreferrer">Control.Arrow.ArrowList</a>, which is using only the first result of the list arrow:</p> <pre><code>single :: ArrowList a =&gt; a b c -&gt; a b c single f = f &gt;&gt;. take 1 </code></pre> <p>We wanted to extract the n-th element:</p> <pre><code>junction :: ArrowList a =&gt; a b c -&gt; Int -&gt; a b c junction a nth = a &gt;&gt;. (take 1 . drop (nth - 1)) </code></pre> <p>Now we can use this new arrow to build up the selector. It’s necessary to use parentheses around the stuff we’re going to filter with <code>junction</code>, because <code>junction</code> modifies an existing arrow.</p> <pre><code>selector :: ArrowXml a =&gt; a XmlTree String selector = getChildren -- There is only one root element. -- For each selected element: Get a list of all children and filter them out. -- The junction function now selects at most one element. &gt;&gt;&gt; (getChildren &gt;&gt;&gt; isElem &gt;&gt;&gt; hasName "a") `junction` 1 -- selects first &lt;a&gt; -- The same thing to select the second &lt;b&gt; for all the &lt;a&gt;s -- (But we had selected only one &lt;a&gt; in this case! -- Imagine commenting out the `junction` 1 above.) &gt;&gt;&gt; (getChildren &gt;&gt;&gt; isElem &gt;&gt;&gt; hasName "b") `junction` 2 -- selects second &lt;b&gt; -- Now get the text of the element. &gt;&gt;&gt; getChildren &gt;&gt;&gt; getText </code></pre> <p>To extract the value and return a Maybe value:</p> <pre><code>main :: IO () main = do let doc = readString [] testXml text &lt;- listToMaybe &lt;$&gt; (runX $ doc &gt;&gt;&gt; selector) print text </code></pre> <p>This outputs <code>Just "second element"</code> with example XML file.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload