8
votes

Lxml élément égalité avec des espaces de noms

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 xxx

mais puisque LXML insiste sur l'espace de noms pré-doté de pré-doté, je devrais faire quelque chose comme xxx

ou effectuez une recherche du nom de l'espace de nom complet de l'attribut NSMAP de l'élément comme celui-ci xxx

s'il y avait un moyen plus facile de convaincre lxml de

  1. Donnez-moi la chaîne de balise sans l'espace de noms annexé, je peux utiliser l'attribut préfixe avec ces informations pour vérifier quelle balise je travaille avec ou
  2. Donnez-moi simplement la chaîne d'étiquette à l'aide du préfixe

    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?


1 commentaires

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.


6 Réponses :


5
votes

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


6 commentaires

Un peu gaspillé, en particulier le [1:] . Pour obtenir la "balise nue", tout ce dont vous avez besoin est elem.tag.split ('}') [- 1] . Notez que ni ce code ni vous ne se soucie d'accolades déséquilibrées.


Utilisé rsplit 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 si ; 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 ()')



22
votes

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


0 commentaires

2
votes

Pour gagner du temps lorsque vous recherchez des balises à volume élevé, telles que p (paragraphe, je présume) dans DOCX ou C (cellule) dans xlsx, il est habituel de configurer La balise complète une fois au niveau mondial ou de classe: xxx

Je n'ai jamais vu une explication de la raison pour laquelle on voudrait utiliser qname () . .

Dans l'autre sens, étant donné une balise complète, vous pouvez extraire la balise de base facilement:

base_tag = FULL_TAG.RSPLIT ("}", 1) [- 1]


0 commentaires

1
votes

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


0 commentaires

5
votes

etree.qname code> devrait être capable de vous obtenir ce que vous voulez.

if tag.namespace == someElement.nsmap["w"] and tag.localname == "p":


0 commentaires

0
votes

Voici ma solution pour restaurer un nom de balise XML réel (source)

supposant que nous avons xml_node variable, une instance de lxml élément

Avant: {http: //} / url} tagname (comme lecture de xml_node.tag Prop)

Après: NSPREFIX: TAGNAME (résultat de xml_get_real_tag_name (xml_node) ) xxx


0 commentaires