XML属性がスキーマを使用してタイムゾーン情報を持っていないことを検証する方法
-
13-12-2019 - |
質問
Schematronを使用してタイムゾーン情報を使用していないことをすべての '署名されていることをすべて検証する方法XPath 1.0を使用する.NET実装を使用しています。
与えられたソースXML:
<?xml version="1.0" encoding="utf-8"?>
<MyData versionDate="2010-12-09" dataBeginDate="2012-03-01" dataEndDate="2012-03-10" extractedWhen="2012-03-09T10:08:40">
<Site Site_key="999">
<SitePatient Patient_key="1">
<txt_Surname value="TEST" signedWhen="2012-03-08T22:02:39" signedWho="SomeName"/>
<txt_GivenNames value="PATIENT" signedWhen="2012-03-08T22:02:39" signedWho="SomeName"/>
<dat_BirthDate value="2010-06-15" signedWhen="2012-03-08T22:02:39" signedWho="SomeName"/>
<sel_Status value="Enrolled" signedWhen="2012-03-08T22:02:39" signedWho="SomeName"/>
<dat_StatusDate value="2012-03-05-05:00" signedWhen="2012-03-08T22:02:39" signedWho="SomeName"/>
</SitePatient>
</Site>
</MyData>
.
XSDファイルのこのスキーマルールを使用する:
<xs:annotation>
<xs:appinfo>
<sch:pattern name="All signedWhen TimeZone constraints">
<sch:rule context="*[@signedWhen]">
<sch:assert test="(substring(@signedWhen,11,12) != '-') and (substring(@signedWhen,11,12) != '+') and (substring(@signedWhen,11,12) != 'Z')">
<name/> must not include TimeZone information
</sch:assert>
</sch:rule>
</sch:pattern>
</xs:appinfo>
</xs:annotation>
.
これらの誤った結果を与えます
タイムゾーン情報がないので、結果を返すべきではありません。
NMatrix.Schematron.ValidationException: Results from Schematron validation:
Results from Schematron validation
From pattern "All signedWhen TimeZone constraints"
Assert fails: txt_Surname must not include TimeZone information
At: /MyData[1]/Site[1]/SitePatient[1]/txt_Surname[1]
<txt_Surname value="TEST" signedWhen="2012-03-08T22:02:39" signedWho="SomeName">...</txt_Surname>
(Line: 5, Column: 6)
Assert fails: txt_GivenNames must not include TimeZone information
At: /MyData[1]/Site[1]/SitePatient[1]/txt_GivenNames[1]
<txt_GivenNames value="PATIENT" signedWhen="2012-03-08T22:02:39" signedWho="SomeName">...</txt_GivenNames>
(Line: 6, Column: 6)
Assert fails: dat_BirthDate must not include TimeZone information
At: /MyData[1]/Site[1]/SitePatient[1]/dat_BirthDate[1]
<dat_BirthDate value="2010-06-15" signedWhen="2012-03-08T22:02:39" signedWho="SomeName">...</dat_BirthDate>
(Line: 7, Column: 6)
Assert fails: sel_Status must not include TimeZone information
At: /MyData[1]/Site[1]/SitePatient[1]/sel_Status[1]
<sel_Status value="Enrolled" signedWhen="2012-03-08T22:02:39" signedWho="SomeName">...</sel_Status>
(Line: 8, Column: 6)
Assert fails: dat_StatusDate must not include TimeZone information
At: /MyData[1]/Site[1]/SitePatient[1]/dat_StatusDate[1]
<dat_StatusDate value="2012-03-05-05:00" signedWhen="2012-03-08T22:02:39" signedWho="SomeName">...</dat_StatusDate>
(Line: 9, Column: 6)
.
編集1:
私はそれを考え出した。テストでXPath 1.0関数 "Substring"を正しく使用していませんでした。
<sch:assert test="(substring(@signedWhen, 11, 1) != '-') and (substring(@signedWhen, 11, 1) != '+') and (substring(@signedWhen, 11, 1) != 'Z')">
.
編集2: W3Schools XSの定義:日付とXS:DateTimeは、任意選択的にマイナス署名された年の可能性については言及していませんでした。そのため、上記のコードが機能しない場合は、下記の答えを参照してください。
編集3: 私が使用しているスキーマは(xmlns:xs="http://www.w3.org/2001/xmlschema")を使用していません。マイナスの署名された年を受け入れず、無効です。安全であるために、私は今からこのコードを使うでしょう:
<sch:assert test="not ( (contains(substring(@signedWhen, 11, 2), '-')) or (contains(@signedWhen, '+')) or (contains(@signedWhen, 'Z')) )">
. 解決
日付や日付etimeを処理したいのかどうかわかりませんが、コードが表示されたら、どちらもいます。あなたのコードは特定のケースでは機能しません。
・字句空間・日付etimeは有限長シーケンスからなる フォームの文字: ' - '?yyyy ' - ' mm ' - ' dd 't' hh ':' mm ':' ss ( 'S +)?(zzzzzz)?、どこに...
詳細についてはさらに読むことができます。(zzz)?
部分はタイムゾーンで、以下のようなものです(同じソース):
タイムゾーンの語彙表現は、次の形式の文字列です。 (( '+' | ' - ')hh ':' mm)|'z'、どこで...
だからあなたのコードは日付や日時のために機能しません:-2010-03-08Z
または2010-03-08T12:01:02.2Z
。
これはより一般的なもの(そしてXPath 1.0):
test="not(
contains(@signedWhen,'+')
or contains(@signedWhen,'Z')
or (contains(@signedWhen, 'T')
and contains(substring-after(@signedWhen ,':'),'-'))
or (not(contains(@signedWhen,'T')) and contains(@signedWhen,':'))
)"
.