파이썬 요소트리 모듈:"find", "findall" 메서드를 사용할 때 일치하는 요소를 찾기 위해 XML 파일의 네임스페이스를 무시하는 방법
▁▁method다싶▁the니습▁i 방법을 사용하고 .findall
xml 합니다.ElementTree
모듈.
그러나 원본 xml 파일(test.xml)에는 네임스페이스가 있습니다.xml 파일의 일부를 샘플로 잘라냅니다.
<?xml version="1.0" encoding="iso-8859-1"?>
<XML_HEADER xmlns="http://www.test.com">
<TYPE>Updates</TYPE>
<DATE>9/26/2012 10:30:34 AM</DATE>
<COPYRIGHT_NOTICE>All Rights Reserved.</COPYRIGHT_NOTICE>
<LICENSE>newlicense.htm</LICENSE>
<DEAL_LEVEL>
<PAID_OFF>N</PAID_OFF>
</DEAL_LEVEL>
</XML_HEADER>
샘플 파이썬 코드는 다음과 같습니다.
from xml.etree import ElementTree as ET
tree = ET.parse(r"test.xml")
el1 = tree.findall("DEAL_LEVEL/PAID_OFF") # Return None
el2 = tree.findall("{http://www.test.com}DEAL_LEVEL/{http://www.test.com}PAID_OFF") # Return <Element '{http://www.test.com}DEAL_LEVEL/PAID_OFF' at 0xb78b90>
사용하지만"{http://www.test.com}"
각 태그 앞에 네임스페이스를 추가하는 것은 매우 불편합니다.
다음과 같은 함수를 사용할 때 네임스페이스를 무시하려면 어떻게 해야 합니까?find
,findall
, ...?
XML 문서 자체를 수정하는 대신 구문 분석한 다음 결과의 태그를 수정하는 것이 가장 좋습니다.이렇게 하면 여러 네임스페이스 및 네임스페이스 별칭을 처리할 수 있습니다.
from io import StringIO # for Python 2 import from StringIO instead
import xml.etree.ElementTree as ET
# instead of ET.fromstring(xml)
it = ET.iterparse(StringIO(xml))
for _, el in it:
_, _, el.tag = el.tag.rpartition('}') # strip ns
root = it.root
이것은 여기서 논의한 내용을 바탕으로 합니다.
구문 분석하기 전에 xml에서 xmlns 특성을 제거하면 트리의 각 태그 앞에 네임스페이스가 추가되지 않습니다.
import re
xmlstring = re.sub(' xmlns="[^"]+"', '', xmlstring, count=1)
지금까지의 답변은 스크립트에 네임스페이스 값을 명시적으로 입력했습니다.보다 일반적인 솔루션의 경우 xml에서 네임스페이스를 추출하는 것이 좋습니다.
import re
def get_namespace(element):
m = re.match('\{.*\}', element.tag)
return m.group(0) if m else ''
찾기 방법으로 사용합니다.
namespace = get_namespace(tree.getroot())
print tree.find('./{0}parent/{0}version'.format(namespace)).text
다음은 속성에서 네임스페이스를 제거하기 위한 @nonagon 응답(태그에서 네임스페이스를 제거함)의 확장입니다.
import io
import xml.etree.ElementTree as ET
# instead of ET.fromstring(xml)
it = ET.iterparse(io.StringIO(xml))
for _, el in it:
if '}' in el.tag:
el.tag = el.tag.split('}', 1)[1] # strip all namespaces
for at in list(el.attrib.keys()): # strip namespaces of attributes too
if '}' in at:
newat = at.split('}', 1)[1]
el.attrib[newat] = el.attrib[at]
del el.attrib[at]
root = it.root
분명히 이것은 XML을 영구적으로 훼손하는 것이지만 고유하지 않은 태그 이름이 없고 원래 이름 공간이 필요한 파일을 쓰지 않기 때문에 허용된다면 액세스가 훨씬 쉬워질 수 있습니다.
구문 분석 모드를 전체적으로 변경하는 대신 구문을 지원하는 개체로 이 모드를 래핑할 수 있습니다.
from xml.parsers import expat
class DisableXmlNamespaces:
def __enter__(self):
self.old_parser_create = expat.ParserCreate
expat.ParserCreate = lambda encoding, sep: self.old_parser_create(encoding, None)
def __exit__(self, type, value, traceback):
expat.ParserCreate = self.oldcreate
다음과 같이 사용할 수 있습니다.
import xml.etree.ElementTree as ET
with DisableXmlNamespaces():
tree = ET.parse("test.xml")
이 방법의 장점은 블록 외부의 관련 없는 코드에 대한 동작을 변경하지 않는다는 것입니다.우연히 expat를 사용한 ericspod 버전을 사용한 후 관련이 없는 라이브러리에서 오류가 발생하여 이를 생성하게 되었습니다.
우아한 문자열 형식 지정 구조도 사용할 수 있습니다.
ns='http://www.test.com'
el2 = tree.findall("{%s}DEAL_LEVEL/{%s}PAID_OFF" %(ns,ns))
또는 PAYED_OFF가 트리의 한 수준에만 표시되는 것이 확실한 경우:
el2 = tree.findall(".//{%s}PAID_OFF" % ns)
3를 python 3.5의 할 수 .find()
를 들어예를들면,
ns= {'xml_test':'http://www.test.com'}
tree = ET.parse(r"test.xml")
el1 = tree.findall("xml_test:DEAL_LEVEL/xml_test:PAID_OFF",ns)
설명서 링크: - https://docs.python.org/3.5/library/xml.etree.elementtree.html#parsing-xml-with-namespaces
나는 이것에 늦을지도 모르지만 나는 생각하지 않습니다.re.sub
좋은 해결책입니다.
그러나 다시 쓰기는xml.parsers.expat
Python 3.x 버전에서는 작동하지 않습니다.
주범은.xml/etree/ElementTree.py
소스 코드 하단 참조
# Import the C accelerators
try:
# Element is going to be shadowed by the C implementation. We need to keep
# the Python version of it accessible for some "creative" by external code
# (see tests)
_Element_Py = Element
# Element, SubElement, ParseError, TreeBuilder, XMLParser
from _elementtree import *
except ImportError:
pass
그건 좀 슬픈 일입니다.
해결책은 그것을 먼저 없애는 것입니다.
import _elementtree
try:
del _elementtree.XMLParser
except AttributeError:
# in case deleted twice
pass
else:
from xml.parsers import expat # NOQA: F811
oldcreate = expat.ParserCreate
expat.ParserCreate = lambda encoding, sep: oldcreate(encoding, None)
Python 3.6에서 테스트되었습니다.
해라try
명령문은 코드의 어딘가에서 모듈을 다시 로드하거나 두 번 가져오면 다음과 같은 이상한 오류가 발생할 때 유용합니다.
- 최대 재귀 깊이가 초과됨
- 특성 오류: XMLParser
젠장, 트리 소스 코드가 정말 지저분해 보입니다.
사용 중인 경우ElementTree
그리고 아닌cElementTree
Expat이 네임스페이스 처리를 무시하도록 강제할 수 있습니다.ParserCreate()
:
from xml.parsers import expat
oldcreate = expat.ParserCreate
expat.ParserCreate = lambda encoding, sep: oldcreate(encoding, None)
ElementTree
호출하여 Expat 사용을 시도합니다.ParserCreate()
그러나 네임스페이스 구분자 문자열을 제공하지 않는 옵션을 제공하지 않습니다. 위의 코드는 이 문자열을 무시하게 하지만 이로 인해 다른 항목이 손상될 수 있음을 경고합니다.
관련 질문에 대한 노나곤의 답변과 mzjn의 답변을 결합해 보겠습니다.
def parse_xml(xml_path: Path) -> Tuple[ET.Element, Dict[str, str]]:
xml_iter = ET.iterparse(xml_path, events=["start-ns"])
xml_namespaces = dict(prefix_namespace_pair for _, prefix_namespace_pair in xml_iter)
return xml_iter.root, xml_namespaces
이 기능을 사용하여 다음 작업을 수행합니다.
네임스페이스와 구문 분석된 트리 개체를 모두 가져오는 반복기를 만듭니다.
작성된 반복기를 반복하여 나중에 전달할 수 있는 네임스페이스를 가져옵니다.
find()
또는findall()
아이맘0이 제안한 통화.구문 분석된 트리의 루트 요소 개체 및 네임스페이스를 반환합니다.
소스 XML이나 결과적으로 구문 분석되는 조작이 없기 때문에 이것이 가장 좋은 접근 방식이라고 생각합니다.xml.etree.ElementTree
관련된 모든 것을 출력합니다.
저는 또한 balmy의 대답이 이 퍼즐의 필수적인 부분을 제공한 것이라고 믿고 싶습니다(반복기에서 구문 분석된 뿌리를 얻을 수 있습니다).그 때까지 저는 실제로 애플리케이션에서 XML 트리를 두 번 통과했습니다(한 번은 네임스페이스, 두 번째는 루트).
우연히 XSD 조건부 유형 할당 기본 유형 혼동이라는 답이 나왔습니다.이것은 주제 질문에 대한 정확한 대답은 아니지만 네임스페이스가 중요하지 않은 경우에 적용될 수 있습니다.
<?xml version="1.0" encoding="UTF-8"?>
<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="test.xsd">
<person version="1">
<firstname>toto</firstname>
<lastname>tutu</lastname>
</person>
</persons>
참고 항목: https://www.w3.org/TR/xmlschema-1/ #xsi_schemaLocation
나한테 효과가 있어요.응용프로그램에서 XML 유효성 검사 절차를 호출합니다.또한 XML을 편집할 때 PyCharm의 유효성 강조 표시 및 자동 완성을 빨리 확인하고 싶습니다.이것.noNamespaceSchemaLocation
속성은 내가 필요로 하는 것을 해줍니다.
다시 확인됨
from xml.etree import ElementTree as ET
tree = ET.parse("test.xml")
el1 = tree.findall("person/firstname")
print(el1[0].text)
el2 = tree.find("person/lastname")
print(el2.text)
반품자
>python test.py
toto
tutu
언급URL : https://stackoverflow.com/questions/13412496/python-elementtree-module-how-to-ignore-the-namespace-of-xml-files-to-locate-ma
'programing' 카테고리의 다른 글
Firebase를 사용한 데이터베이스 스타일 쿼리 (0) | 2023.06.12 |
---|---|
Firebase Console에서 Google 프로젝트를 제거하는 방법은 무엇입니까? (0) | 2023.06.12 |
Python Infinity - 주의 사항이 있습니까? (0) | 2023.06.12 |
iOS에서 뷰 계층을 검사하려면 어떻게 해야 합니까? (0) | 2023.06.12 |
Oracle의 SYS_GUID() UUID RFC 4122가 호환됩니까? (0) | 2023.06.12 |