在 python 中导入 XML 命名空间
Import XML namespace in python
我在编码方面完全是菜鸟,我学习 IT,并且有一个学校项目,我必须在该项目中将 .txt 文件转换为 XML 文件。我设法创建了一棵树和子元素,但必须在代码中放置一些 XML 名称空间。因为最终 XML 文件必须在一个程序中打开,该程序会为您提供 table 的信息,以及更多信息。但是如果没有来自 XML 命名空间的方案,它就不会打开任何东西。有人可以帮助我如何在我的代码中加入 .xsd 吗?
这是方案:
http://www.pufbih.ba/images/stories/epp_docs/PaketniUvozObrazaca_V1_0.xsd
必须创建的 XML 文件示例:
http://www.pufbih.ba/images/stories/epp_docs/4200575050089_1022.xml
并且在第一行中有我必须输入的方案:“urn:PaketniUvozObrazaca_V1_0.xsd”
这是到目前为止创建的代码:
import xml.etree.ElementTree as xml
def GenerateXML(GIP1022):
root=xml.Element("PaketniUvozObrazaca")
p1=xml.Element("PodaciOPoslodavcu")
root.append(p1)
jib=xml.SubElement(p1,"JIBPoslodavca")
jib.text="4254160150005"
pos=xml.SubElement(p1,"NazivPoslodavca")
pos.text="MOJATVRTKA d.o.o. ORAŠJE"
zah=xml.SubElement(p1,"BrojZahtjeva")
zah.text="8"
datz=xml.SubElement(p1,"DatumPodnosenja")
datz.text="2021-01-01"
tree=xml.ElementTree(root)
with open(GIP1022,"wb") as files:
tree.write(files)
if __name__=="__main__":
GenerateXML("primjer.xml")
official documentation is not super explicit as to how one works with namespaces in ElementTree, but the core of it is that ElementTree takes a very fundamental(ist) approach: instead of manipulating namespace prefixes / aliases, elementtree uses Clark's Notation.
例如
<bar xmlns="foo">
或
<x:bar xmlns:x="foo">
(foo
命名空间中的元素 bar
)将被写入
{foo}bar
>>> tostring(Element('{foo}bar'), encoding='unicode')
'<ns0:bar xmlns:ns0="foo" />'
或者(有时更方便创作和操作)您可以使用 QName objects,它可以采用 Clark 符号标记名称,或单独采用命名空间和标记名称:
>>> tostring(Element(QName('foo', 'bar')), encoding='unicode')
'<ns0:bar xmlns:ns0="foo" />'
因此,虽然 ElementTree 本身没有命名空间对象,但您可以像这样创建命名空间对象,可能是通过部分应用 QName 的助手:
>>> root = Element(ns("PaketniUvozObrazaca"))
>>> SubElement(root, ns("PodaciOPoslodavcu"))
<Element <QName '{urn:PaketniUvozObrazaca_V1_0.xsd}PodaciOPoslodavcu'> at 0x7f502481bdb0>
>>> tostring(root, encoding='unicode')
'<ns0:PaketniUvozObrazaca xmlns:ns0="urn:PaketniUvozObrazaca_V1_0.xsd"><ns0:PodaciOPoslodavcu /></ns0:PaketniUvozObrazaca>'
这里有几个重要的注意事项:
首先,正如您所见,序列化时的前缀是任意的,这与 ElementTree 对 XML 的原教旨主义方法保持一致(前缀 应该 无关紧要),但它后来发展了一个“register_namespace”全局函数,允许注册特定的前缀:
>>> register_namespace('xxx', 'urn:PaketniUvozObrazaca_V1_0.xsd')
>>> tostring(root, encoding='unicode')
'<xxx:PaketniUvozObrazaca xmlns:xxx="urn:PaketniUvozObrazaca_V1_0.xsd"><xxx:PodaciOPoslodavcu /></xxx:PaketniUvozObrazaca>'
您还可以将单个 default_namespace
传递给(某些)序列化函数以指定默认命名空间:
>>> tostring(root, encoding='unicode', default_namespace='urn:PaketniUvozObrazaca_V1_0.xsd')
'<PaketniUvozObrazaca xmlns="urn:PaketniUvozObrazaca_V1_0.xsd"><PodaciOPoslodavcu /></PaketniUvozObrazaca>'
第二个可能更大的问题是 ElementTree 不支持验证。
Python 标准库不提供对任何验证解析器或树构建器的支持,无论是 DTD、rng、xml 模式还是任何东西。默认情况下不是,也不是可选的。
lxml 可能是支持验证(多种类型的模式)的主要替代方案,其核心 API 遵循 ElementTree 但在多个方面和方向上扩展了它(包括更精确的命名空间前缀支持, 和前缀往返)。但即便如此,验证(AFAIK)大多是明确的,至少在生成/序列化文档时是这样。
tree.write()
方法接受一个 default_namespace
参数。
如果将该行更改为以下内容会怎样?
tree.write(files, default_namespace="urn:PaketniUvozObrazaca_V1_0.xsd")
您想要的是将默认命名空间声明 (xmlns="urn:PaketniUvozObrazaca_V1_0.xsd"
) 添加到根元素。我已经编辑了问题中的代码以向您展示如何完成此操作。
import xml.etree.ElementTree as ET
def GenerateXML(GIP1022):
# Create the PaketniUvozObrazaca root element in the urn:PaketniUvozObrazaca_V1_0.xsd namespace
root = ET.Element("{urn:PaketniUvozObrazaca_V1_0.xsd}PaketniUvozObrazaca")
# Add subelements
p1 = ET.Element("PodaciOPoslodavcu")
root.append(p1)
jib = ET.SubElement(p1,"JIBPoslodavca")
jib.text = "4254160150005"
pos = ET.SubElement(p1,"NazivPoslodavca")
pos.text = "MOJATVRTKA d.o.o. ORAŠJE"
zah = ET.SubElement(p1,"BrojZahtjeva")
zah.text = "8"
datz = ET.SubElement(p1,"DatumPodnosenja")
datz.text = "2021-01-01"
# Make urn:PaketniUvozObrazaca_V1_0.xsd the default namespace (no prefix)
ET.register_namespace("", "urn:PaketniUvozObrazaca_V1_0.xsd")
# Prettify output (requires Python 3.9)
ET.indent(root)
tree = ET.ElementTree(root)
with open(GIP1022,"wb") as files:
tree.write(files)
if __name__=="__main__":
GenerateXML("primjer.xml")
primjer.xml 的内容:
<PaketniUvozObrazaca xmlns="urn:PaketniUvozObrazaca_V1_0.xsd">
<PodaciOPoslodavcu>
<JIBPoslodavca>4254160150005</JIBPoslodavca>
<NazivPoslodavca>MOJATVRTKA d.o.o. ORAŠJE</NazivPoslodavca>
<BrojZahtjeva>8</BrojZahtjeva>
<DatumPodnosenja>2021-01-01</DatumPodnosenja>
</PodaciOPoslodavcu>
</PaketniUvozObrazaca>
请注意,只有根元素明确绑定到代码中的名称空间。添加子元素时,它们不需要位于命名空间中。最终结果是一个 XML 文档 (primjer.xml),其中所有元素都属于相同的默认命名空间。
以上并不是在命名空间中创建元素的唯一方法。例如,可以使用 QName
class 代替 {namespace-uri}name
表示法。参见 。
我在编码方面完全是菜鸟,我学习 IT,并且有一个学校项目,我必须在该项目中将 .txt 文件转换为 XML 文件。我设法创建了一棵树和子元素,但必须在代码中放置一些 XML 名称空间。因为最终 XML 文件必须在一个程序中打开,该程序会为您提供 table 的信息,以及更多信息。但是如果没有来自 XML 命名空间的方案,它就不会打开任何东西。有人可以帮助我如何在我的代码中加入 .xsd 吗?
这是方案: http://www.pufbih.ba/images/stories/epp_docs/PaketniUvozObrazaca_V1_0.xsd
必须创建的 XML 文件示例: http://www.pufbih.ba/images/stories/epp_docs/4200575050089_1022.xml
并且在第一行中有我必须输入的方案:“urn:PaketniUvozObrazaca_V1_0.xsd”
这是到目前为止创建的代码:
import xml.etree.ElementTree as xml
def GenerateXML(GIP1022):
root=xml.Element("PaketniUvozObrazaca")
p1=xml.Element("PodaciOPoslodavcu")
root.append(p1)
jib=xml.SubElement(p1,"JIBPoslodavca")
jib.text="4254160150005"
pos=xml.SubElement(p1,"NazivPoslodavca")
pos.text="MOJATVRTKA d.o.o. ORAŠJE"
zah=xml.SubElement(p1,"BrojZahtjeva")
zah.text="8"
datz=xml.SubElement(p1,"DatumPodnosenja")
datz.text="2021-01-01"
tree=xml.ElementTree(root)
with open(GIP1022,"wb") as files:
tree.write(files)
if __name__=="__main__":
GenerateXML("primjer.xml")
official documentation is not super explicit as to how one works with namespaces in ElementTree, but the core of it is that ElementTree takes a very fundamental(ist) approach: instead of manipulating namespace prefixes / aliases, elementtree uses Clark's Notation.
例如
<bar xmlns="foo">
或
<x:bar xmlns:x="foo">
(foo
命名空间中的元素 bar
)将被写入
{foo}bar
>>> tostring(Element('{foo}bar'), encoding='unicode')
'<ns0:bar xmlns:ns0="foo" />'
或者(有时更方便创作和操作)您可以使用 QName objects,它可以采用 Clark 符号标记名称,或单独采用命名空间和标记名称:
>>> tostring(Element(QName('foo', 'bar')), encoding='unicode')
'<ns0:bar xmlns:ns0="foo" />'
因此,虽然 ElementTree 本身没有命名空间对象,但您可以像这样创建命名空间对象,可能是通过部分应用 QName 的助手:
>>> root = Element(ns("PaketniUvozObrazaca"))
>>> SubElement(root, ns("PodaciOPoslodavcu"))
<Element <QName '{urn:PaketniUvozObrazaca_V1_0.xsd}PodaciOPoslodavcu'> at 0x7f502481bdb0>
>>> tostring(root, encoding='unicode')
'<ns0:PaketniUvozObrazaca xmlns:ns0="urn:PaketniUvozObrazaca_V1_0.xsd"><ns0:PodaciOPoslodavcu /></ns0:PaketniUvozObrazaca>'
这里有几个重要的注意事项:
首先,正如您所见,序列化时的前缀是任意的,这与 ElementTree 对 XML 的原教旨主义方法保持一致(前缀 应该 无关紧要),但它后来发展了一个“register_namespace”全局函数,允许注册特定的前缀:
>>> register_namespace('xxx', 'urn:PaketniUvozObrazaca_V1_0.xsd')
>>> tostring(root, encoding='unicode')
'<xxx:PaketniUvozObrazaca xmlns:xxx="urn:PaketniUvozObrazaca_V1_0.xsd"><xxx:PodaciOPoslodavcu /></xxx:PaketniUvozObrazaca>'
您还可以将单个 default_namespace
传递给(某些)序列化函数以指定默认命名空间:
>>> tostring(root, encoding='unicode', default_namespace='urn:PaketniUvozObrazaca_V1_0.xsd')
'<PaketniUvozObrazaca xmlns="urn:PaketniUvozObrazaca_V1_0.xsd"><PodaciOPoslodavcu /></PaketniUvozObrazaca>'
第二个可能更大的问题是 ElementTree 不支持验证。
Python 标准库不提供对任何验证解析器或树构建器的支持,无论是 DTD、rng、xml 模式还是任何东西。默认情况下不是,也不是可选的。
lxml 可能是支持验证(多种类型的模式)的主要替代方案,其核心 API 遵循 ElementTree 但在多个方面和方向上扩展了它(包括更精确的命名空间前缀支持, 和前缀往返)。但即便如此,验证(AFAIK)大多是明确的,至少在生成/序列化文档时是这样。
tree.write()
方法接受一个 default_namespace
参数。
如果将该行更改为以下内容会怎样?
tree.write(files, default_namespace="urn:PaketniUvozObrazaca_V1_0.xsd")
您想要的是将默认命名空间声明 (xmlns="urn:PaketniUvozObrazaca_V1_0.xsd"
) 添加到根元素。我已经编辑了问题中的代码以向您展示如何完成此操作。
import xml.etree.ElementTree as ET
def GenerateXML(GIP1022):
# Create the PaketniUvozObrazaca root element in the urn:PaketniUvozObrazaca_V1_0.xsd namespace
root = ET.Element("{urn:PaketniUvozObrazaca_V1_0.xsd}PaketniUvozObrazaca")
# Add subelements
p1 = ET.Element("PodaciOPoslodavcu")
root.append(p1)
jib = ET.SubElement(p1,"JIBPoslodavca")
jib.text = "4254160150005"
pos = ET.SubElement(p1,"NazivPoslodavca")
pos.text = "MOJATVRTKA d.o.o. ORAŠJE"
zah = ET.SubElement(p1,"BrojZahtjeva")
zah.text = "8"
datz = ET.SubElement(p1,"DatumPodnosenja")
datz.text = "2021-01-01"
# Make urn:PaketniUvozObrazaca_V1_0.xsd the default namespace (no prefix)
ET.register_namespace("", "urn:PaketniUvozObrazaca_V1_0.xsd")
# Prettify output (requires Python 3.9)
ET.indent(root)
tree = ET.ElementTree(root)
with open(GIP1022,"wb") as files:
tree.write(files)
if __name__=="__main__":
GenerateXML("primjer.xml")
primjer.xml 的内容:
<PaketniUvozObrazaca xmlns="urn:PaketniUvozObrazaca_V1_0.xsd">
<PodaciOPoslodavcu>
<JIBPoslodavca>4254160150005</JIBPoslodavca>
<NazivPoslodavca>MOJATVRTKA d.o.o. ORAŠJE</NazivPoslodavca>
<BrojZahtjeva>8</BrojZahtjeva>
<DatumPodnosenja>2021-01-01</DatumPodnosenja>
</PodaciOPoslodavcu>
</PaketniUvozObrazaca>
请注意,只有根元素明确绑定到代码中的名称空间。添加子元素时,它们不需要位于命名空间中。最终结果是一个 XML 文档 (primjer.xml),其中所有元素都属于相同的默认命名空间。
以上并不是在命名空间中创建元素的唯一方法。例如,可以使用 QName
class 代替 {namespace-uri}name
表示法。参见