可以在XSD中实现Unicode规范无壳匹配吗?

时间:2017-09-12 19:33:47

标签: xml unicode xsd

我正在为一个数据模型的XML模式工作,该模式涉及从几乎所有Unicode字符中提取的不区分大小写的键。在此上下文中,“不区分大小写”是根据Unicode规范无标记匹配算法(Chapter 3 of version 10.0 of the Unicode specification中的定义D145)定义的。无壳匹配与XSD 1.1身份约束无法很好地匹配,因此我正在考虑用于定义必要的键唯一性约束的各种备选方案,理想情况下不会丢失原始的,非规范化的键形式。

目前,我只是简单地将按键限制为以符合规范的标准化形式呈现,与规范的无壳匹配一致,以便它们可以直接相互比较。为了使它有用,它必须不依赖于扩展或特定于实现的行为,尽管我愿意依赖明确定义的可选行为,例如使用unicode-normalize() XPath函数来规范化以形成NFD。 / p>

将来,我可能还想验证两个字符串是规范的无壳匹配(即约束两个属性值或元素的文本内容和其中一个属性值是彼此的规范无壳匹配),但这是一个单独的问题。

这是一个简化的示例模式,我认为它非常接近于我想要的东西:

<xsd:schema
    version="1.1"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:fn="http://www.w3.org/2005/xpath-functions"
    xmlns:my="urn:x-myns"
    targetNamespace="urn:x-myns"
    elementFormDefault="qualified">

  <xsd:element name="table" type="my:tableType">
    <xsd:key name="keyKey">
      <xsd:selector xpath="my:entry"/>
      <xsd:field xpath="@key"/>
    </xsd:key>
  </xsd:element>

  <xsd:complexType name="tableType">
    <xsd:sequence>
      <xsd:element name="entry" type="my:entryType"
                   minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="entryType">
    <xsd:simpleContent>
      <xsd:extension base="xsd:string">
        <xsd:attribute name="key" type="xsd:string"/>

        <!-- MY BEST ATTEMPT SO FAR: -->
        <xsd:assert test="@key=fn:unicode-normalize(fn:lower-case(
            fn:unicode-normalize(@key, 'NFD')), 'NFD')" />

      </xsd:extension>
    </xsd:simpleContent>
  </xsd:complexType>

</xsd:schema>

这足以拒绝

<table xmlns="urn:x-myns">
  <entry key="Clé">Value1</entry>
</table>

(“Clé”应显示为“cle&amp;#x0301;”或相同字符序列的等效表示),但它与数据的本机规范化不完全匹配,因为Unicode案例折叠不等于较低 - 在某些情况下。所以,

  • 有没有办法在这种情况下产生一个真正的Unicode案例折叠规范化形式,受制于我提出的限制?
  • 我真的需要吗?如果我的模式中的断言测试的表单作为无壳匹配行为的基础,总是产生与Unicode的标准规范无标记匹配算法相同的结果,那么我可以忍受我所拥有的。

1 个答案:

答案 0 :(得分:1)

你问:

  

有没有办法在这种情况下产生一个真正的Unicode案例折叠规范化形式,受制于我提出的限制?

如果通过&#34;真正的Unicode案例折叠规范化形式&#34;你的意思是将Unicode Case_Folding()映射应用于字符串的结果,我认为答案是(可能)&#34; no&#34;,这就是原因。

对于您正在使用的方法,您需要一个函数(或者在您的示例中为函数组合),您可以在断言中调用它。因此,当且仅当存在可以调用以生成它的内置函数的简单组合时,应该可以获得真正的大小写折叠形式。

如果Case_Folding只是将旧字符替换为旧字符,理论上可以通过调用translate()来处理它,但参数字符串将无法管理。但是Case_Folding映射(如果我已经理解了你指向的文档)一些字符到字符串(和/或一些字符串到字符串),这使得translate()无法访问。

不通过Unicode字符数据库中的案例折叠和下框条目进入,我不知道可以肯定地证明它无法完成。 (也许调用小写()然后明智地使用replace()就可以了 - 但我希望它过于笨拙。

当然可以写一个XQuery或XSLT函数来进行大小写折叠操作(而不是下壳和上壳)。但是没有办法在XSD断言中声明一个函数。

如果您能找到愿意接受XPath 3.0而不是2.0的XSD架构验证器,那么从理论上讲编写自己的函数是可行的。但是,除非您可以将尽可能多的细节卸载到Unicode数据库的XML表示中,否则它将会很麻烦,这意味着只有在XSD处理器愿意评估对doc()的调用时它才会起作用。

所以在实践中我认为答案是否定的,除非你愿意花费不同寻常的时间来实现它并且也有一些运气。

  

我真的需要吗?如果我的模式中的断言测试的表单作为无壳匹配行为的基础,总是产生与Unicode的标准规范无标记匹配算法相同的结果,那么我可以接受我所拥有的。 / p>

我想在这里,答案是&#34;不是&#34;。第4节&#34;默认案例折叠&#34;在您指向的URI处读取:

  

任何两个字符串在任何完整的情况下被认为是彼此的大小写变体   大小写转换,toUppercase(X),toLowercase(X)或toTitlecase(X)将折叠为相同   toCasefold(X)操作的字符串

由于XPath小写()函数被指定为实现Unicode小写映射,我认为这给你的结果是任何字符串S1和S2的小写($ S1)eq小写(在Unicode toCasefold()操作下,$ S2)将是相等的。 Unicode段落的措辞留下了一些可能性,即一些不是彼此的大小写变体的字符串将折叠到toCasefold()下的相同字符串,但我希望他们所有的意思都是这种情况折叠会影响标准化以及套管。如果是这样,那么我认为你对unicode-normalize()的调用将处理这些情况。 (如果有其他字符串对,其中toCasefold()返回相等的值,但是unicode-normalize(小写())没有,那么你的断言将无法接受你想要接受的一些对。但那些是什么成对的字符串是?)

这个答案不像我希望的那样清晰,而且我怀疑我已经告诉过你一些你不知道的事情了。没有比我有时间更多的时间在Unicode数据库中进行研究,我不认为可能有更明确的答案。但如果你大多希望独立的观察者确认你似乎在正确的轨道上,我当然可以这样做。干得好!还有祝你好运!