【问题标题】:Is it possible to get the type of an XML node as it was defined in XSD?是否可以获得在 XSD 中定义的 XML 节点的类型?
【发布时间】:2011-01-25 23:02:07
【问题描述】:

我正在用 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,我想检查它们是否都有填充英语的字段。很容易检查&lt;lang xml:lang="en"&gt;&lt;/lang&gt; 是否为空,但允许根本不指定此标记。

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

更新

由于在验证期间我的 XML 会根据 XSD 检查,因此验证引擎知道所有节点的类型。 7个月前我有一个类似的问题,仍然没有答案。他们是相关的,恕我直言。 Validating and filling default values in XML based on XSD in Python

【问题讨论】:

    标签: python xml xsd xsd-validation


    【解决方案1】:

    如果问题是:如何找到给定 XML 节点的类型名称? 答案是使用xpath in python 进行查找。在 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 来强制执行您正在寻找的标准。

    【讨论】:

    • 我想查找在 XSD 中定义为 zwv:description 的所有 XML 节点,而不是 XSD 中的所有定义。例如,在我的 XSD 中,我可以定义两个 wakeupNote:一个 inside deviceDescriptionzwv:description,另一个标签内的一个为 zwv:shortdescription。所以在我的 XML 中,我将有两种类型的wakeupNote。我只需要选择类型为zwv:description 的那些。怎么办?
    • 如果编辑不符合您的需要,请添加评论。请不要在没有机会澄清问题和答案的情况下投反对票。
    • 我越想这个,就越需要了解用例才能做出好的推荐。你是如何解析 XML 的?架构多久更改一次? XSD 是你的还是对方的?如果是对方,为什么要强加额外的验证?
    • 此 XSD 可能会被其他方更改而无需任何通知,而且检查起来很复杂。将不时检查 XML(它们的数量每天都会增加)以查看是否有未翻译的值。我的想法是基于这样的信念,即在验证期间,XML 引擎会检查所有 XML 字段并将其与 XSD 中定义的类型相关联。所以应该可以从引擎中提取这些信息。与我有关填充默认值的相关问题相同。
    • 您的想法是解析 XML 并在 XSD 中以相同的类型执行 XPath 以查找 XML 中每个节点的类型?这是正面的解决方案,看起来很重。我不能从验证引擎中得到这个吗?否则我实际上会编写自己的验证引擎的一半。
    【解决方案2】:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多