Je tente d'utiliser LXML pour analyser le contenu d'un document .Docx. Je comprends que LXML remplace les préfixes d'espace de noms avec l'espace de noms actuel, mais cela en fait une réelle douleur à vérifier quel type d'étiquette d'élément je travaille. J'aimerais pouvoir faire quelque chose comme mais puisque LXML insiste sur l'espace de noms pré-doté de pré-doté, je devrais faire quelque chose comme p> ou effectuez une recherche du nom de l'espace de nom complet de l'attribut NSMAP de l'élément comme celui-ci p> s'il y avait un moyen plus facile de convaincre lxml de p > Cela permettrait d'économiser beaucoup de frappes lors de l'écriture de cet analyseur. Est-ce possible? Est-ce que je manque quelque chose dans la documentation? P> p>
6 Réponses :
Je n'ai pas pu trouver un moyen d'obtenir le nom de balise non-réparé à partir d'un élément - LXML considère la partie de l'espace de noms complet du nom de la balise. Voici quelques options qui peuvent aider ..
Vous pouvez également utiliser la classe qname code> pour construire une balisePaçaille pour comparaisons: p>
lxml.etree.Element('{foo')
ValueError: Invalid tag name
Un peu gaspillé, en particulier le [1:] code>. Pour obtenir la "balise nue", tout ce dont vous avez besoin est
elem.tag.split ('}') [- 1] code>. Notez que ni ce code ni vous ne se soucie d'accolades déséquilibrées.
Utilisé rsplit code> pour être plus efficace, en supposant que les URL d'espace de noms ont tendance à être longues.
Bon point. Vous n'avez pas débarrassé de l'instruction code> si code>; Les balises non-noms d'espace ont tendance à être courtes.
Ma tête jongle 5 choses différentes en ce moment ... simplifiées à une ligne. Merci John.
[SIMIER] J'allais dire "... des accolades déséquilibrées, qui sont impossibles" mais pensaient que je serais considéré comme Sybil Fawlty comme "Statin '" Statin' "évident" :)
+1 pour suggérer la classe QName. En ce qui concerne l'obtention du nom local (si vous avez vraiment), vous pouvez utiliser XPath: ELEM.XPATH ('Nom local ()') code>
Peut-être utiliser Nom local () :
import lxml.etree as ET tree = ET.fromstring('<root xmlns:f="foo"><f:test/></root>') elt=tree[0] print(elt.xpath('local-name()')) # test
Pour gagner du temps lorsque vous recherchez des balises à volume élevé, telles que Je n'ai jamais vu une explication de la raison pour laquelle on voudrait utiliser Dans l'autre sens, étant donné une balise complète, vous pouvez extraire la balise de base facilement: p> p code> (paragraphe, je présume) dans DOCX ou
C code> (cellule) dans xlsx, il est habituel de configurer La balise complète une fois au niveau mondial ou de classe:
qname () code>. p>.
base_tag = FULL_TAG.RSPLIT ("}", 1) [- 1] code > p> p>
Je ne suis pas expert en python, mais j'ai aussi eu ce problème (Windows 7 "Contacts" Fichiers). J'ai écrit la fonction suivante pour le système LXML.
Cette fonction prend un élément et renvoie sa balise avec le préfixe substitué à partir de la balise NS du fichier. P>
from lxml import etree def denstag(ee): tag = ee.tag for ns in ee.nsmap: prefix = "{"+ee.nsmap[ns]+"}" if tag.startswith(prefix): return ns+":"+tag[len(prefix):] return tag
etree.qname code>
devrait être capable de vous obtenir ce que vous voulez.
if tag.namespace == someElement.nsmap["w"] and tag.localname == "p":
Voici ma solution pour restaurer un nom de balise XML réel (source)
supposant que nous avons Avant: Après: xml_node code> variable, une instance de lxml
élément code> p>
{http: //} / url} tagname code> (comme lecture de
xml_node.tag code> Prop) p>
NSPREFIX: TAGNAME CODE> (résultat de
xml_get_real_tag_name (xml_node) code>) p>
Vous ne voulez jamais faire correspondre au préfixe, car le préfixe est totalement arbitraire. Un fichier .Docx valide pourrait avoir un préfixe, même 'XYZ', tant qu'il a été attribué à la même chaîne de points de noms. LXML vous fait une faveur en vous empêchant de compter sur le préfixe d'espace de noms pour la correspondance.