diff --git a/netdiff/__init__.py b/netdiff/__init__.py
index 03f18af..54f1e3e 100644
--- a/netdiff/__init__.py
+++ b/netdiff/__init__.py
@@ -3,4 +3,5 @@
from .parsers.olsr import OlsrParser # noqa
from .parsers.batman import BatmanParser # noqa
from .parsers.netjson import NetJsonParser # noqa
+from .parsers.cnml import CnmlParser # noqa
from .utils import diff # noqa
diff --git a/netdiff/parsers/cnml.py b/netdiff/parsers/cnml.py
new file mode 100644
index 0000000..90df872
--- /dev/null
+++ b/netdiff/parsers/cnml.py
@@ -0,0 +1,51 @@
+import networkx
+import libcnml
+import os
+import six
+
+try:
+ import urlparse
+except ImportError:
+ import urllib.parse as urlparse
+
+from .base import BaseParser
+from ..exceptions import NetParserException
+
+
+class CnmlParser(BaseParser):
+ """ CNML 0.1 parser """
+ protocol = 'static'
+ version = '0.1'
+ metric = None
+
+ def _to_python(self, data):
+ if isinstance(data, six.string_types):
+ up = urlparse.urlparse(data)
+ # if it looks like a file path
+ if os.path.isfile(data) or up.scheme in ['http', 'https']:
+ return libcnml.CNMLParser(data)
+ else:
+ raise NetParserException('Could not decode CNML data')
+ elif isinstance(data, libcnml.CNMLParser):
+ return data
+ else:
+ raise NetParserException('Could not find valid data to parse')
+
+ def parse(self, data):
+ """
+ Extract information from a CNML file to generate a NetworkX Graph object.
+ """
+ graph = networkx.Graph()
+
+ # loop over links and create networkx graph
+ # Add only working nodes with working links
+ for link in data.get_inner_links():
+ if link.status != libcnml.libcnml.Status.WORKING:
+ continue
+ interface_a, interface_b = link.getLinkedInterfaces()
+ source = interface_a.ipv4
+ dest = interface_b.ipv4
+ # add link to Graph
+ graph.add_edge(source, dest, weight=1)
+
+ self.graph = graph
diff --git a/requirements.txt b/requirements.txt
index 679cb70..389426d 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
networkx
requests
six
+libcnml
diff --git a/tests/cnml/__init__.py b/tests/cnml/__init__.py
new file mode 100644
index 0000000..1a8f173
--- /dev/null
+++ b/tests/cnml/__init__.py
@@ -0,0 +1 @@
+from .tests import TestCnmlParser # noqa
diff --git a/tests/cnml/tests.py b/tests/cnml/tests.py
new file mode 100644
index 0000000..0972938
--- /dev/null
+++ b/tests/cnml/tests.py
@@ -0,0 +1,119 @@
+import os
+import six
+import networkx
+
+from netdiff import CnmlParser
+from netdiff import diff
+from netdiff.exceptions import NetParserException
+from netdiff.tests import TestCase
+
+
+__all__ = ['TestCnmlParser']
+
+
+CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))
+cnml1 = '{0}/../static/26494_detail_1.cnml'.format(CURRENT_DIR)
+cnml2 = '{0}/../static/26494_detail_2.cnml'.format(CURRENT_DIR)
+cnml3 = '{0}/../static/26494_detail_3.cnml'.format(CURRENT_DIR)
+
+
+class TestCnmlParser(TestCase):
+
+ def test_parse(self):
+ p = CnmlParser(cnml1)
+ self.assertIsInstance(p.graph, networkx.Graph)
+
+ def test_parse_exception(self):
+ with self.assertRaises(NetParserException):
+ CnmlParser('{ "test": "test" }')
+
+ def test_parse_exception2(self):
+ with self.assertRaises(NetParserException):
+ CnmlParser('telnet://127.0.0.1:9090')
+
+ def test_json_dict(self):
+ p = CnmlParser(cnml1)
+ data = p.json(dict=True)
+ self.assertIsInstance(data, dict)
+ self.assertEqual(data['type'], 'NetworkGraph')
+ self.assertEqual(data['protocol'], 'static')
+ self.assertEqual(data['version'], '0.1')
+ self.assertEqual(data['revision'], None)
+ self.assertEqual(data['metric'], None)
+ self.assertIsInstance(data['nodes'], list)
+ self.assertIsInstance(data['links'], list)
+ self.assertEqual(len(data['nodes']), 5)
+ self.assertEqual(len(data['links']), 3)
+
+ def test_json_string(self):
+ p = CnmlParser(cnml1)
+ data = p.json()
+ self.assertIsInstance(data, six.string_types)
+ self.assertIn('NetworkGraph', data)
+ self.assertIn('protocol', data)
+ self.assertIn('version', data)
+ self.assertIn('revision', data)
+ self.assertIn('metric', data)
+ self.assertIn('0.1', data)
+ self.assertIn('links', data)
+ self.assertIn('nodes', data)
+
+ def test_no_changes(self):
+ old = CnmlParser(cnml1)
+ new = CnmlParser(cnml1)
+ result = diff(old, new)
+ self.assertTrue(type(result) is dict)
+ self.assertTrue(type(result['added']) is list)
+ self.assertTrue(type(result['removed']) is list)
+ # ensure there are no differences
+ self.assertEqual(len(result['added']), 0)
+ self.assertEqual(len(result['removed']), 0)
+
+ def test_added_1_link(self):
+ old = CnmlParser(cnml1)
+ new = CnmlParser(cnml2)
+ result = diff(old, new)
+ # ensure there are differences
+ self.assertEqual(len(result['added']), 1)
+ self.assertEqual(len(result['removed']), 0)
+ # ensure 1 link added
+ self.assertIn('10.228.172.97', result['added'][0])
+ self.assertIn('10.228.172.101', result['added'][0])
+
+ def test_removed_1_link(self):
+ old = CnmlParser(cnml2)
+ new = CnmlParser(cnml1)
+ result = diff(old, new)
+ self.assertTrue(type(result) is dict)
+ self.assertTrue(type(result['added']) is list)
+ self.assertTrue(type(result['removed']) is list)
+ # ensure there are differences
+ self.assertEqual(len(result['added']), 0)
+ self.assertEqual(len(result['removed']), 1)
+ # ensure 1 link removed
+ self.assertIn('10.228.172.97', result['removed'][0])
+ self.assertIn('10.228.172.101', result['removed'][0])
+
+ def test_simple_diff(self):
+ old = CnmlParser(cnml1)
+ new = CnmlParser(cnml3)
+ result = diff(old, new)
+ # ensure there are differences
+ self.assertEqual(len(result['added']), 2)
+ self.assertEqual(len(result['removed']), 2)
+ # ensure 2 links added
+ self._test_expected_links(
+ links=result['added'],
+ expected_links=[
+ ('10.228.172.97', '10.228.172.101'),
+ ('10.228.172.194', '10.228.172.193'),
+ ]
+ )
+ # ensure 2 links removed
+ self._test_expected_links(
+ links=result['removed'],
+ expected_links=[
+ ('10.228.172.33', '10.228.172.34'),
+ ('10.228.172.33', '10.228.172.36'),
+ ]
+ )
diff --git a/tests/static/26494_detail_1.cnml b/tests/static/26494_detail_1.cnml
new file mode 100644
index 0000000..f8dad5a
--- /dev/null
+++ b/tests/static/26494_detail_1.cnml
@@ -0,0 +1,56 @@
+
+
+
+
+ <p>Ciudad de Málaga, ciudad costera llana con algunas colinas y montes al norte.<br />
+<a style="color: rgb(47, 65, 111); text-decoration: none;" href="http://malaga.guifi.net/">http://malaga.guifi.net/</a> <-- Portal Málaga Guifi.net en Málaga<br />
+<a href="http://malagaguifi.wordpress.com/">http://malagaguifi.wordpress.com/</a> <-- Blog de Málaga Guifi</p>
+<p>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="content-type" content="text/html; charset=utf-8"> </meta>
+</meta>
+</p> <p>29008 Málaga</p><p> Nodo proyectado en calle Arriate nº 24</p><p> Nodo en la zona oeste de Málaga con enlace al supernodo (proyectado) en MLGTorreDelCarmen01</p><p>La versió del firmware és XS5.ar2313.v3.3.2.4257.090214.1458</p>Requereix usuari de proxy<p> Zona más alta entre las zonas Centro y Oeste de Málaga</p>La casa de la Buena Vida<br /><p>En una azotea </p><p>ultima planta de edificio de seis pisos</p><p>Fibra fibrita bonita... ;-)</p> <p>Comparto una conexión a internet de 1 mb. Por el momento es un AP 802.11n con openwrt con proxy y cortafuegos, y solo están abiertos los puertos 80 y 443 (contactar si se necesitan otros puertos). Solo pido un uso razonable, porque 1 mb no da para mucho.<br />
+<br />
+Me reservo el derecho a:<br />
+-Bloquear las webs que considere de dudosa legalidad.<br />
+-Eliminar a aquellos usuarios que no hagan un uso responsable de la conexión.<br />
+-Cesar la conexión en cualquier momento.<br />
+-Modificar cualquiera de las condiciones anteriores o añadir nuevas.<br />
+<br />
+Con vistas a ampliar el alcance en un futuro, dispongo de un Nanostation 5 (5.8 ghz) + AP 2.4 ghz (Fonera con dd-wrt + antena direccional 7 dBi). Posibilidad de instalar hardware más decente para enlazar, en cuanto haya más nodos/supernodos más cercanos a mi entorno.</p> Centro Guadalinfo<br /><p>Técnicos en Tiendas Virtuales (T2V)</p>
+<p><a href="http://www.t2v.com/">http://www.t2v.com/</a></p>
+<p>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" /></p><p><a href="http://jesustenorio.files.wordpress.com/2011/05/012.jpg" target="_blank"><img width="600" height="159" src="http://jesustenorio.files.wordpress.com/2011/05/012.jpg" alt="" /></a></p>
+<p>Dado que por diversos motivos no puedo instalar un supernodo, solo podría conectarme en modo cliente a algunas de las antenas existentes del centro de Málaga.</p><p>Ático vistas Este 180º.</p><p>
+<meta content="text/html; charset=utf-8" http-equiv="content-type"> </meta>
+</p>
+<div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(241, 242, 242); font: normal normal normal 12px/170% Verdana, sans-serif; color: rgb(73, 73, 73); background-position: initial initial; background-repeat: initial initial; ">
+<p style="margin: 0.6em 0px 1.2em; padding: 0px;"><img alt="" src="http://guifi.net/files/images/logo_lainvisible.png" /></p>
+<p style="margin-top: 0.6em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">Centro social y cultural de gestión ciudadana La Invisible. En la calle Nosquera 9.</p>
+<p style="margin: 0.6em 0px 1.2em; padding: 0px;"><a style="color: rgb(47, 65, 111); text-decoration: none; " href="http://www.lainvisible.net/">http://www.lainvisible.net/</a></p>
+</div>
+<p> </p>
+<p> </p>
+<p> </p>
+<p>
+<meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>Proxy disponible para compartir conexión de 200Mbps simétricos<br /><p>Cruce de Martinez de la Rosa con Eugenio Gross.</p><p>El Mirador, Málaga.</p>
+<p>Existen ya antenas como se puede ver <a href="http://maps.google.es/maps?f=q&source=s_q&hl=es&geocode=&q=olletas+malaga&aq=&sll=36.735514,-4.406033&sspn=0.037282,0.090551&ie=UTF8&hq=olletas&hnear=M%C3%A1laga,+Andaluc%C3%ADa&ll=36.766598,-4.377129&spn=0,0.022638&z=16&layer=c&cbll=36.766516,-4.377044&panoid=FPTz8QN59NFqnsh6-yCvyA&cbp=12,114.85,,0,-17.5">aquí</a>.</p><p class="rtecenter"><a target="_blank" href="https://lh5.googleusercontent.com/-bGNA2hBL2y8/T-SFBqy-K0I/AAAAAAAAIKU/ZvmgVOlrHus/s912/MLGNuevaMalaga.jpg"><img width="912" height="255" alt="" src="https://lh5.googleusercontent.com/-bGNA2hBL2y8/T-SFBqy-K0I/AAAAAAAAIKU/ZvmgVOlrHus/s912/MLGNuevaMalaga.jpg" /></a></p><p>Supernodo de Floren</p><br />
+<h3>La altura es la que tiene 6 plantas más bajo y una caseta para el cuarto de motores del ascensor en el tejado. Total 8 plantas sobre el suelo.</h3><p>c/Pinosol 12, 29012 Málaga (zona Camino Nuevo/Barcenillas)</p><p>Acceso por Paseo Marítimo Antonio Machado 62 o Calle de Tomás Echevarría 6.</p> Puerto de la Torre, Calle Lanzarote del Lago <p>Nostracon, fibra fibrita fibrosa... ;-)</p><a href="https://wiki.15m.cc/wiki/Comedor-Centro_Social_autogestionado_%22Er_banco_G%C3%BCeno%22">Comedor-Centro Social autogestionado "Er banco Güeno"</a><br />
+<ul>
+ <li>Blog: <a href="http://erbancogueno.blogspot.com.es/">http://erbancogueno.blogspot.com.es/</a></li>
+</ul><p>calle ramon maria perez de torre nº 1</p><p>De momento se ha montado un supertrasto mikrotik routerboard con una radio y antena omnidireccional para dar cobertura a todo el barrio y cualquier otra zona circundante, que no son pocas gracias a las geniales vistas desde el punto donde se ha instalado.</p>
+<p>Ampliable a supernodo en un futuro.</p>Edificio El Navío<p>Nodo ubicado en la Torre del Carmen, junto al río Guadalmedina, frente al puente de Antonio Machado (que enlaza el Paseo Marítimo de Antonio Machado con el Puerto de Málaga), con orientación sur.</p><ul>
+ <li>1x Routerboard 433AH</li>
+ <li>2x Radio R52N</li>
+ <li>2x Antena sectorial 90º 17dBi 5GHz</li>
+ <li>2x Pigtail 18 cm. RG-316 pigtail MMCX to N Bulkhead</li>
+ <li>1x Adaptador PoE 24V</li>
+ <li>1x Caja</li>
+</ul>
+<p>TOTAL: ~381€ (para apadrinar)</p><p>El <b>Distrito Campanillas</b> o <b>Distrito 9</b> es uno de los diez distritos en que está dividida administrativamente la ciudad de <a title="Málaga" href="http://es.wikipedia.org/wiki/M%C3%A1laga">Málaga</a>. Según datos del <a title="Ayuntamiento de Málaga" href="http://es.wikipedia.org/wiki/Ayuntamiento_de_M%C3%A1laga">Ayuntamiento de Málaga</a> de enero de <a title="2005" href="http://es.wikipedia.org/wiki/2005">2005</a>, en el distrito 9 estaban censados 16.177 ciudadanos.</p>
+<p>El distrito 9 es el distrito más occidental de la ciudad, situado en el límite con los términos municipales de <a title="Alhaurín de la Torre" href="http://es.wikipedia.org/wiki/Alhaur%C3%ADn_de_la_Torre">Alhaurín de la Torre</a>, <a title="Cártama" href="http://es.wikipedia.org/wiki/C%C3%A1rtama">Cártama</a> y <a title="Almogía" href="http://es.wikipedia.org/wiki/Almog%C3%ADa">Almogía</a>, en el valle formado por el <a title="Río Campanillas" href="http://es.wikipedia.org/wiki/R%C3%ADo_Campanillas">río Campanillas</a>. Al sur bordea la ribera del <a title="Guadalhorce" href="http://es.wikipedia.org/wiki/Guadalhorce">Guadalhorce</a> y el distrito de <a title="Churriana" href="http://es.wikipedia.org/wiki/Churriana">Churriana</a>. Por el este limita con los distritos <a title="Cruz de Humilladero" href="http://es.wikipedia.org/wiki/Cruz_de_Humilladero">Cruz de Humilladero</a> y <a title="Puerto de la Torre" href="http://es.wikipedia.org/wiki/Puerto_de_la_Torre">Puerto de la Torre</a>.</p><p>Churriana es un barrio perteneciente al distrito homónimo de la ciudad andaluza de Málaga, España. Según la delimitación oficial del ayuntamiento, límita al norte y al este con el área del Aeropuerto de Málaga-Costa del Sol; al surestee, con el barrio de Las Espeñuelas; al sur, con los barrios de Hacienda Platero y Heliomar; al oeste, con los barrios de El Cuartón y La Tosca; y al noroeste, con el barrio de Los Paredones.</p>
+
+<p><a href="https://es.wikipedia.org/wiki/Churriana_%28barrio%29">https://es.wikipedia.org/wiki/Churriana_(barrio)</a></p>
+
+
+
diff --git a/tests/static/26494_detail_2.cnml b/tests/static/26494_detail_2.cnml
new file mode 100644
index 0000000..924df55
--- /dev/null
+++ b/tests/static/26494_detail_2.cnml
@@ -0,0 +1,56 @@
+
+
+
+
+ <p>Ciudad de Málaga, ciudad costera llana con algunas colinas y montes al norte.<br />
+<a style="color: rgb(47, 65, 111); text-decoration: none;" href="http://malaga.guifi.net/">http://malaga.guifi.net/</a> <-- Portal Málaga Guifi.net en Málaga<br />
+<a href="http://malagaguifi.wordpress.com/">http://malagaguifi.wordpress.com/</a> <-- Blog de Málaga Guifi</p>
+<p>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="content-type" content="text/html; charset=utf-8"> </meta>
+</meta>
+</p> <p>29008 Málaga</p><p> Nodo proyectado en calle Arriate nº 24</p><p> Nodo en la zona oeste de Málaga con enlace al supernodo (proyectado) en MLGTorreDelCarmen01</p><p>La versió del firmware és XS5.ar2313.v3.3.2.4257.090214.1458</p>Requereix usuari de proxy<p> Zona más alta entre las zonas Centro y Oeste de Málaga</p>La casa de la Buena Vida<br /><p>En una azotea </p><p>ultima planta de edificio de seis pisos</p><p>Fibra fibrita bonita... ;-)</p> <p>Comparto una conexión a internet de 1 mb. Por el momento es un AP 802.11n con openwrt con proxy y cortafuegos, y solo están abiertos los puertos 80 y 443 (contactar si se necesitan otros puertos). Solo pido un uso razonable, porque 1 mb no da para mucho.<br />
+<br />
+Me reservo el derecho a:<br />
+-Bloquear las webs que considere de dudosa legalidad.<br />
+-Eliminar a aquellos usuarios que no hagan un uso responsable de la conexión.<br />
+-Cesar la conexión en cualquier momento.<br />
+-Modificar cualquiera de las condiciones anteriores o añadir nuevas.<br />
+<br />
+Con vistas a ampliar el alcance en un futuro, dispongo de un Nanostation 5 (5.8 ghz) + AP 2.4 ghz (Fonera con dd-wrt + antena direccional 7 dBi). Posibilidad de instalar hardware más decente para enlazar, en cuanto haya más nodos/supernodos más cercanos a mi entorno.</p> Centro Guadalinfo<br /><p>Técnicos en Tiendas Virtuales (T2V)</p>
+<p><a href="http://www.t2v.com/">http://www.t2v.com/</a></p>
+<p>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" /></p><p><a href="http://jesustenorio.files.wordpress.com/2011/05/012.jpg" target="_blank"><img width="600" height="159" src="http://jesustenorio.files.wordpress.com/2011/05/012.jpg" alt="" /></a></p>
+<p>Dado que por diversos motivos no puedo instalar un supernodo, solo podría conectarme en modo cliente a algunas de las antenas existentes del centro de Málaga.</p><p>Ático vistas Este 180º.</p><p>
+<meta content="text/html; charset=utf-8" http-equiv="content-type"> </meta>
+</p>
+<div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(241, 242, 242); font: normal normal normal 12px/170% Verdana, sans-serif; color: rgb(73, 73, 73); background-position: initial initial; background-repeat: initial initial; ">
+<p style="margin: 0.6em 0px 1.2em; padding: 0px;"><img alt="" src="http://guifi.net/files/images/logo_lainvisible.png" /></p>
+<p style="margin-top: 0.6em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">Centro social y cultural de gestión ciudadana La Invisible. En la calle Nosquera 9.</p>
+<p style="margin: 0.6em 0px 1.2em; padding: 0px;"><a style="color: rgb(47, 65, 111); text-decoration: none; " href="http://www.lainvisible.net/">http://www.lainvisible.net/</a></p>
+</div>
+<p> </p>
+<p> </p>
+<p> </p>
+<p>
+<meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>Proxy disponible para compartir conexión de 200Mbps simétricos<br /><p>Cruce de Martinez de la Rosa con Eugenio Gross.</p><p>El Mirador, Málaga.</p>
+<p>Existen ya antenas como se puede ver <a href="http://maps.google.es/maps?f=q&source=s_q&hl=es&geocode=&q=olletas+malaga&aq=&sll=36.735514,-4.406033&sspn=0.037282,0.090551&ie=UTF8&hq=olletas&hnear=M%C3%A1laga,+Andaluc%C3%ADa&ll=36.766598,-4.377129&spn=0,0.022638&z=16&layer=c&cbll=36.766516,-4.377044&panoid=FPTz8QN59NFqnsh6-yCvyA&cbp=12,114.85,,0,-17.5">aquí</a>.</p><p class="rtecenter"><a target="_blank" href="https://lh5.googleusercontent.com/-bGNA2hBL2y8/T-SFBqy-K0I/AAAAAAAAIKU/ZvmgVOlrHus/s912/MLGNuevaMalaga.jpg"><img width="912" height="255" alt="" src="https://lh5.googleusercontent.com/-bGNA2hBL2y8/T-SFBqy-K0I/AAAAAAAAIKU/ZvmgVOlrHus/s912/MLGNuevaMalaga.jpg" /></a></p><p>Supernodo de Floren</p><br />
+<h3>La altura es la que tiene 6 plantas más bajo y una caseta para el cuarto de motores del ascensor en el tejado. Total 8 plantas sobre el suelo.</h3><p>c/Pinosol 12, 29012 Málaga (zona Camino Nuevo/Barcenillas)</p><p>Acceso por Paseo Marítimo Antonio Machado 62 o Calle de Tomás Echevarría 6.</p> Puerto de la Torre, Calle Lanzarote del Lago <p>Nostracon, fibra fibrita fibrosa... ;-)</p><a href="https://wiki.15m.cc/wiki/Comedor-Centro_Social_autogestionado_%22Er_banco_G%C3%BCeno%22">Comedor-Centro Social autogestionado "Er banco Güeno"</a><br />
+<ul>
+ <li>Blog: <a href="http://erbancogueno.blogspot.com.es/">http://erbancogueno.blogspot.com.es/</a></li>
+</ul><p>calle ramon maria perez de torre nº 1</p><p>De momento se ha montado un supertrasto mikrotik routerboard con una radio y antena omnidireccional para dar cobertura a todo el barrio y cualquier otra zona circundante, que no son pocas gracias a las geniales vistas desde el punto donde se ha instalado.</p>
+<p>Ampliable a supernodo en un futuro.</p>Edificio El Navío<p>Nodo ubicado en la Torre del Carmen, junto al río Guadalmedina, frente al puente de Antonio Machado (que enlaza el Paseo Marítimo de Antonio Machado con el Puerto de Málaga), con orientación sur.</p><ul>
+ <li>1x Routerboard 433AH</li>
+ <li>2x Radio R52N</li>
+ <li>2x Antena sectorial 90º 17dBi 5GHz</li>
+ <li>2x Pigtail 18 cm. RG-316 pigtail MMCX to N Bulkhead</li>
+ <li>1x Adaptador PoE 24V</li>
+ <li>1x Caja</li>
+</ul>
+<p>TOTAL: ~381€ (para apadrinar)</p><p>El <b>Distrito Campanillas</b> o <b>Distrito 9</b> es uno de los diez distritos en que está dividida administrativamente la ciudad de <a title="Málaga" href="http://es.wikipedia.org/wiki/M%C3%A1laga">Málaga</a>. Según datos del <a title="Ayuntamiento de Málaga" href="http://es.wikipedia.org/wiki/Ayuntamiento_de_M%C3%A1laga">Ayuntamiento de Málaga</a> de enero de <a title="2005" href="http://es.wikipedia.org/wiki/2005">2005</a>, en el distrito 9 estaban censados 16.177 ciudadanos.</p>
+<p>El distrito 9 es el distrito más occidental de la ciudad, situado en el límite con los términos municipales de <a title="Alhaurín de la Torre" href="http://es.wikipedia.org/wiki/Alhaur%C3%ADn_de_la_Torre">Alhaurín de la Torre</a>, <a title="Cártama" href="http://es.wikipedia.org/wiki/C%C3%A1rtama">Cártama</a> y <a title="Almogía" href="http://es.wikipedia.org/wiki/Almog%C3%ADa">Almogía</a>, en el valle formado por el <a title="Río Campanillas" href="http://es.wikipedia.org/wiki/R%C3%ADo_Campanillas">río Campanillas</a>. Al sur bordea la ribera del <a title="Guadalhorce" href="http://es.wikipedia.org/wiki/Guadalhorce">Guadalhorce</a> y el distrito de <a title="Churriana" href="http://es.wikipedia.org/wiki/Churriana">Churriana</a>. Por el este limita con los distritos <a title="Cruz de Humilladero" href="http://es.wikipedia.org/wiki/Cruz_de_Humilladero">Cruz de Humilladero</a> y <a title="Puerto de la Torre" href="http://es.wikipedia.org/wiki/Puerto_de_la_Torre">Puerto de la Torre</a>.</p><p>Churriana es un barrio perteneciente al distrito homónimo de la ciudad andaluza de Málaga, España. Según la delimitación oficial del ayuntamiento, límita al norte y al este con el área del Aeropuerto de Málaga-Costa del Sol; al surestee, con el barrio de Las Espeñuelas; al sur, con los barrios de Hacienda Platero y Heliomar; al oeste, con los barrios de El Cuartón y La Tosca; y al noroeste, con el barrio de Los Paredones.</p>
+
+<p><a href="https://es.wikipedia.org/wiki/Churriana_%28barrio%29">https://es.wikipedia.org/wiki/Churriana_(barrio)</a></p>
+
+
+
diff --git a/tests/static/26494_detail_3.cnml b/tests/static/26494_detail_3.cnml
new file mode 100644
index 0000000..6c64a81
--- /dev/null
+++ b/tests/static/26494_detail_3.cnml
@@ -0,0 +1,56 @@
+
+
+
+
+ <p>Ciudad de Málaga, ciudad costera llana con algunas colinas y montes al norte.<br />
+<a style="color: rgb(47, 65, 111); text-decoration: none;" href="http://malaga.guifi.net/">http://malaga.guifi.net/</a> <-- Portal Málaga Guifi.net en Málaga<br />
+<a href="http://malagaguifi.wordpress.com/">http://malagaguifi.wordpress.com/</a> <-- Blog de Málaga Guifi</p>
+<p>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<meta http-equiv="content-type" content="text/html; charset=utf-8"> </meta>
+</meta>
+</p> <p>29008 Málaga</p><p> Nodo proyectado en calle Arriate nº 24</p><p> Nodo en la zona oeste de Málaga con enlace al supernodo (proyectado) en MLGTorreDelCarmen01</p><p>La versió del firmware és XS5.ar2313.v3.3.2.4257.090214.1458</p>Requereix usuari de proxy<p> Zona más alta entre las zonas Centro y Oeste de Málaga</p>La casa de la Buena Vida<br /><p>En una azotea </p><p>ultima planta de edificio de seis pisos</p><p>Fibra fibrita bonita... ;-)</p> <p>Comparto una conexión a internet de 1 mb. Por el momento es un AP 802.11n con openwrt con proxy y cortafuegos, y solo están abiertos los puertos 80 y 443 (contactar si se necesitan otros puertos). Solo pido un uso razonable, porque 1 mb no da para mucho.<br />
+<br />
+Me reservo el derecho a:<br />
+-Bloquear las webs que considere de dudosa legalidad.<br />
+-Eliminar a aquellos usuarios que no hagan un uso responsable de la conexión.<br />
+-Cesar la conexión en cualquier momento.<br />
+-Modificar cualquiera de las condiciones anteriores o añadir nuevas.<br />
+<br />
+Con vistas a ampliar el alcance en un futuro, dispongo de un Nanostation 5 (5.8 ghz) + AP 2.4 ghz (Fonera con dd-wrt + antena direccional 7 dBi). Posibilidad de instalar hardware más decente para enlazar, en cuanto haya más nodos/supernodos más cercanos a mi entorno.</p> Centro Guadalinfo<br /><p>Técnicos en Tiendas Virtuales (T2V)</p>
+<p><a href="http://www.t2v.com/">http://www.t2v.com/</a></p>
+<p>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" /></p><p><a href="http://jesustenorio.files.wordpress.com/2011/05/012.jpg" target="_blank"><img width="600" height="159" src="http://jesustenorio.files.wordpress.com/2011/05/012.jpg" alt="" /></a></p>
+<p>Dado que por diversos motivos no puedo instalar un supernodo, solo podría conectarme en modo cliente a algunas de las antenas existentes del centro de Málaga.</p><p>Ático vistas Este 180º.</p><p>
+<meta content="text/html; charset=utf-8" http-equiv="content-type"> </meta>
+</p>
+<div style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(241, 242, 242); font: normal normal normal 12px/170% Verdana, sans-serif; color: rgb(73, 73, 73); background-position: initial initial; background-repeat: initial initial; ">
+<p style="margin: 0.6em 0px 1.2em; padding: 0px;"><img alt="" src="http://guifi.net/files/images/logo_lainvisible.png" /></p>
+<p style="margin-top: 0.6em; margin-right: 0px; margin-bottom: 1.2em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">Centro social y cultural de gestión ciudadana La Invisible. En la calle Nosquera 9.</p>
+<p style="margin: 0.6em 0px 1.2em; padding: 0px;"><a style="color: rgb(47, 65, 111); text-decoration: none; " href="http://www.lainvisible.net/">http://www.lainvisible.net/</a></p>
+</div>
+<p> </p>
+<p> </p>
+<p> </p>
+<p>
+<meta content="text/html; charset=utf-8" http-equiv="content-type" /></p>Proxy disponible para compartir conexión de 200Mbps simétricos<br /><p>Cruce de Martinez de la Rosa con Eugenio Gross.</p><p>El Mirador, Málaga.</p>
+<p>Existen ya antenas como se puede ver <a href="http://maps.google.es/maps?f=q&source=s_q&hl=es&geocode=&q=olletas+malaga&aq=&sll=36.735514,-4.406033&sspn=0.037282,0.090551&ie=UTF8&hq=olletas&hnear=M%C3%A1laga,+Andaluc%C3%ADa&ll=36.766598,-4.377129&spn=0,0.022638&z=16&layer=c&cbll=36.766516,-4.377044&panoid=FPTz8QN59NFqnsh6-yCvyA&cbp=12,114.85,,0,-17.5">aquí</a>.</p><p class="rtecenter"><a target="_blank" href="https://lh5.googleusercontent.com/-bGNA2hBL2y8/T-SFBqy-K0I/AAAAAAAAIKU/ZvmgVOlrHus/s912/MLGNuevaMalaga.jpg"><img width="912" height="255" alt="" src="https://lh5.googleusercontent.com/-bGNA2hBL2y8/T-SFBqy-K0I/AAAAAAAAIKU/ZvmgVOlrHus/s912/MLGNuevaMalaga.jpg" /></a></p><p>Supernodo de Floren</p><br />
+<h3>La altura es la que tiene 6 plantas más bajo y una caseta para el cuarto de motores del ascensor en el tejado. Total 8 plantas sobre el suelo.</h3><p>c/Pinosol 12, 29012 Málaga (zona Camino Nuevo/Barcenillas)</p><p>Acceso por Paseo Marítimo Antonio Machado 62 o Calle de Tomás Echevarría 6.</p> Puerto de la Torre, Calle Lanzarote del Lago <p>Nostracon, fibra fibrita fibrosa... ;-)</p><a href="https://wiki.15m.cc/wiki/Comedor-Centro_Social_autogestionado_%22Er_banco_G%C3%BCeno%22">Comedor-Centro Social autogestionado "Er banco Güeno"</a><br />
+<ul>
+ <li>Blog: <a href="http://erbancogueno.blogspot.com.es/">http://erbancogueno.blogspot.com.es/</a></li>
+</ul><p>calle ramon maria perez de torre nº 1</p><p>De momento se ha montado un supertrasto mikrotik routerboard con una radio y antena omnidireccional para dar cobertura a todo el barrio y cualquier otra zona circundante, que no son pocas gracias a las geniales vistas desde el punto donde se ha instalado.</p>
+<p>Ampliable a supernodo en un futuro.</p>Edificio El Navío<p>Nodo ubicado en la Torre del Carmen, junto al río Guadalmedina, frente al puente de Antonio Machado (que enlaza el Paseo Marítimo de Antonio Machado con el Puerto de Málaga), con orientación sur.</p><ul>
+ <li>1x Routerboard 433AH</li>
+ <li>2x Radio R52N</li>
+ <li>2x Antena sectorial 90º 17dBi 5GHz</li>
+ <li>2x Pigtail 18 cm. RG-316 pigtail MMCX to N Bulkhead</li>
+ <li>1x Adaptador PoE 24V</li>
+ <li>1x Caja</li>
+</ul>
+<p>TOTAL: ~381€ (para apadrinar)</p><p>El <b>Distrito Campanillas</b> o <b>Distrito 9</b> es uno de los diez distritos en que está dividida administrativamente la ciudad de <a title="Málaga" href="http://es.wikipedia.org/wiki/M%C3%A1laga">Málaga</a>. Según datos del <a title="Ayuntamiento de Málaga" href="http://es.wikipedia.org/wiki/Ayuntamiento_de_M%C3%A1laga">Ayuntamiento de Málaga</a> de enero de <a title="2005" href="http://es.wikipedia.org/wiki/2005">2005</a>, en el distrito 9 estaban censados 16.177 ciudadanos.</p>
+<p>El distrito 9 es el distrito más occidental de la ciudad, situado en el límite con los términos municipales de <a title="Alhaurín de la Torre" href="http://es.wikipedia.org/wiki/Alhaur%C3%ADn_de_la_Torre">Alhaurín de la Torre</a>, <a title="Cártama" href="http://es.wikipedia.org/wiki/C%C3%A1rtama">Cártama</a> y <a title="Almogía" href="http://es.wikipedia.org/wiki/Almog%C3%ADa">Almogía</a>, en el valle formado por el <a title="Río Campanillas" href="http://es.wikipedia.org/wiki/R%C3%ADo_Campanillas">río Campanillas</a>. Al sur bordea la ribera del <a title="Guadalhorce" href="http://es.wikipedia.org/wiki/Guadalhorce">Guadalhorce</a> y el distrito de <a title="Churriana" href="http://es.wikipedia.org/wiki/Churriana">Churriana</a>. Por el este limita con los distritos <a title="Cruz de Humilladero" href="http://es.wikipedia.org/wiki/Cruz_de_Humilladero">Cruz de Humilladero</a> y <a title="Puerto de la Torre" href="http://es.wikipedia.org/wiki/Puerto_de_la_Torre">Puerto de la Torre</a>.</p><p>Churriana es un barrio perteneciente al distrito homónimo de la ciudad andaluza de Málaga, España. Según la delimitación oficial del ayuntamiento, límita al norte y al este con el área del Aeropuerto de Málaga-Costa del Sol; al surestee, con el barrio de Las Espeñuelas; al sur, con los barrios de Hacienda Platero y Heliomar; al oeste, con los barrios de El Cuartón y La Tosca; y al noroeste, con el barrio de Los Paredones.</p>
+
+<p><a href="https://es.wikipedia.org/wiki/Churriana_%28barrio%29">https://es.wikipedia.org/wiki/Churriana_(barrio)</a></p>
+
+
+