4

我正在用 python 解析 XML。我有一个 XSD 架构来验证 XML。我能否获得在 XSD 中定义的 XML 特定节点的类型?

例如,我的 XML(小部分)是

<deviceDescription>
  <wakeupNote>
    <lang xml:lang="ru">Русский</lang>
    <lang xml:lang="en">English</lang>
  </wakeupNote> 
</deviceDescription>

我的 XSD 是(又是其中的一小部分):

<xsd:element name="deviceDescription" type="zwv:deviceDescription" minOccurs="0"/>

<xsd:complexType name="deviceDescription">
  <xsd:sequence>
    <xsd:element name="wakeupNote" type="zwv:description" minOccurs="0">
      <xsd:unique name="langDescrUnique">
        <xsd:selector xpath="zwv:lang"/> 
        <xsd:field xpath="@xml:lang"/>  
      </xsd:unique>
    </xsd:element> 
  </xsd:sequence>
</xsd:complexType>

<xsd:complexType name="description">
  <xsd:sequence>
    <xsd:element name="lang" maxOccurs="unbounded">
      <xsd:complexType>
        <xsd:simpleContent>
          <xsd:extension base="xsd:string">
            <xsd:attribute ref="xml:lang" use="required"/>
          </xsd:extension>
        </xsd:simpleContent>
      </xsd:complexType>
    </xsd:element>
  </xsd:sequence> 
</xsd:complexType>

在解析期间,我想知道我的标签wakeupNote在 XSD 中定义为complexType zwv:description。如何做到这一点(在python中)?

我需要这个做什么?假设我有很多这样的 XML,我想检查它们是否都有填充英语的字段。很容易检查 是否<lang xml:lang="en"></lang>为空,但允许根本不指定此标签。

所以我们的想法是获取所有可能有语言描述的标签,并检查标签是否存在并且是否有en<lang>的非空内容。

UPD

由于在验证期间我的 XML 是针对 XSD 进行检查的,因此验证引擎知道所有节点的类型。7个月前我有一个类似的问题,仍然没有答案。他们是相关的,恕我直言。在 Python 中基于 XSD 验证和填充 XML 中的默认值

4

2 回答 2

0

您是对的,验证器必须知道它验证的所有元素和属性的类型关联,因此验证器能够提供对该信息的访问。

然而,无论好坏,调用者和验证者之间的 API 以及调用者可用的验证相关信息的选择都是完全由实现定义的。一些验证器(Xerces J 是一个值得注意的例子)提供了非常全面的验证信息;其他人没有。

在不知道您使用的是什么验证器的情况下,没有人可以确定地告诉您您正在寻找的类型信息是否可用。由于您正在调用验证器,因此必须有一个 API;如果可以通过 API 获得类型关联,那么文档大概会这样说。如果 API 没有提供对它的访问,可能是因为底层模式验证器没有提供对信息的访问,也可能是因为 API 的创建者没有看到重点;您的工作(如果您想进一步研究)将找出其中的情况,然后尝试说服相关各方,让信息可用是有用的。

如果您无法通过 API 访问信息,您可以使用 David W 的另一个答案中提到的方法的更复杂版本来帮助自己。XSD 模式的一个属性是任何元素的管理类型是严格来说是从验证根到该元素的路径的函数,因此原则上很简单(如果在实践中有点乏味的话),对于文档实例中的任何元素,如果文档实例针对特定模式进行验证。例如,对于您提到的情况,很容易判断给定的祖先是否wakeupNote具有deviceDescriptionotherElement作为祖先,或者如果wakeupNote两者都有,并根据该知识推断出适当的管理类型定义。

以这种方式帮助自己可能需要大量的工作。如果有通用工具来计算这些信息并以各种形式访问它会有所帮助,但如果有的话,我不知道。(我确实知道有人可以付费构建这样的工具。)所以如果我是你,我会首先尝试通过 API 获取信息。

于 2012-08-16T23:31:18.510 回答
0

如果问题是:如何找到给定 XML 节点的类型名称?答案是在python中使用xpath来查找。在 xsd 上运行的 xpath 将是

//element[@name='wakeupNote']/@type

这应该返回 zwv:description。如果它返回两种类型,您将不得不从根开始

/root/foo/wakeupNote (type A)
/root/bar/wakeupNote (type B)

从根部往下走会很乏味。您必须同时查找匿名类型和命名类型。

如果问题是:如何找到给定类型的所有 XML 节点?如果 schema 会经常变化,你可以在使用上面的方法解析它时测试每个节点的类型。

如果架构是众所周知的、固定的,并且您正在寻找的节点可以通过 XPATH 找到,那么您可以测试每个节点。

//@xml:lang='en'

然后使用python检查每个的长度。

在稳定模式的情况下,您可以编写第二个 XSD 来强制执行您正在寻找的标准。

于 2011-02-03T03:54:56.803 回答