Eine PDF Version dieser Aufgabe finden Sie hier.
Implementieren Sie folgendes literate Haskell Modul, in dem für eine XML-Struktur die XPath Achsen implementiert werden sollen.
\documentclass[a4paper]{article}
\usepackage[ngerman]{babel}
\usepackage[utf8x]{inputenc}
\usepackage[german=guillemets]{csquotes}
%include polycode.fmt
\setlength\parindent{0pt}
\setlength{\parskip}{5pt plus 2pt minus 1pt}
\usepackage{enumitem}
\begin{document}
\author{}
\title{Übungsblatt 4}
\maketitle
\section*{Aufgabe 4: XPath Achsen}
In diesem Übungsblatt sei eine kleine Datenstruktur für XML-Dokumente gegeben.
> module XML where
Wir sehen zwei Arten von XML-Knoten vor. Textknoten und Elementknoten. Ein Knoten
hat als ersten Parameter einen Verweis auf den Elternknoten, sofern es sich selbst
nicht um die Wurzel handelt. Der zweite Parameter beider Konstruktoren zeigt an,
um das wie vielte Kind es sich handelt, wenn der Knoten einen Elternknoten hat.
Wurzelknoten sind dabei mit $-1$ markiert.
> data XML
> = Text (Maybe XML) Index String
> |Element (Maybe XML) Index Name Attributes ChildNodes
Ein Textknoten hat nur den eigentlichen Text. Ein Elementknoten einen Tagnamen,
eine Attributliste und die Liste der Kinder.
Dabei wurden folgende Typsynonyme verwendet
> type Name = String
> type ChildNodes = [XML]
> type Attribute = (Key,Value)
> type Attributes = [Attribute]
> type Key = String
> type Value = String
> type Index = Int
Eine simple Instanz der Typklasse \verb+Show+ serialisiert die XML-Knoten
in XML-Syntax.
> instance (Show XML) where
> show (Text _ _ txt) = txt
> show (Element _ _ name attrs cs)
> = "<"++name++(concat (map showAttr attrs))++">"
> ++concat (map show cs)++"</"++name++">"
> where
> showAttr (k,v) = " "++k++"=\""++v++"\""
Eine eigene Instanz für Eq prüft auf Gleichheit.
> instance (Eq XML) where
> (Text _ i1 txt1) == (Text _ i2 txt2) = txt1 == txt2
> (Element _ i1 name1 attrs1 cs1) == (Element _ i2 name2 attrs2 cs2)
> = name1==name2 && attrs1==attrs2 && cs1==cs2
> _ == y = False
Eine Konstruktorfunktion zur Erzeugung von Elementen sei gegeben. Diese
setzt den Verweis auf den Elternknoten korrekt und die Indexangabe über
die Position in der Kinderliste. Der komplete Kindbaum muss dabei neu erzeugt werden.
> mkElement name attrs cs = r
> where
> r = (Element Nothing (-1) name attrs (map (setParent r) (zip [0..] cs)))
> setParent p (n, (Text _ _ txt) ) = Text (Just p) n txt
> setParent p (n, (Element _ _ na attrs cs)) =
> let p2 = Element (Just p) n na attrs (map (setParent2 p2) cs)
> in p2
>
> setParent2 p ((Text _ n txt) ) = Text (Just p) n txt
> setParent2 p ((Element _ n na attrs cs)) =
> let p2 = Element (Just p) n na attrs (map (setParent2 p2) cs)
> in p2
Praktischer Weise sei auch eine Konstruktorfunktion für Textknoten vorgesehen.
> mkText = Text Nothing (-1)
Implementieren Sie Funktionen für die XPath Achsen:
> type XPathAchsis = XML -> [XML]
\begin{enumerate}[label=\alph*)]
\item Implementieren Sie die Achse {\em self}:
> self :: XPathAchsis
> self _ = []
\item Implementieren Sie die Achse {\em parent}:
> parent :: XPathAchsis
> parent _ = []
\item Implementieren Sie die Achse {\em ancestor}:
> ancestor :: XPathAchsis
> ancestor _ = []
\item Implementieren Sie die Achse {\em ancestor-or-self}:
> ancestorOrSelf :: XPathAchsis
> ancestorOrSelf _ = []
\item Implementieren Sie die Achse {\em child}:
> child :: XPathAchsis
> child _ = []
\item Implementieren Sie die Achse {\em descendant}:
> descendant :: XPathAchsis
> descendant _ = []
\item Implementieren Sie die Achse {\em descendant-or-self}:
> descendantOrSelf :: XPathAchsis
> descendantOrSelf _ = []
\item Implementieren Sie die Achse {\em Following-sibbling}:
> followingSibbling :: XPathAchsis
> followingSibbling _ = []
\item Implementieren Sie die Achse {\em preceding-sibbling}:
> precedingSibbling :: XPathAchsis
> precedingSibbling _ = []
\item Implementieren Sie die Achse {\em Following}:
> following :: XPathAchsis
> following _ = []
\item Implementieren Sie die Achse {\em preceding}:
> preceding :: XPathAchsis
> preceding _ = []
\end{enumerate}
\end{document}