1

Schematron を使用して、すべての「signedWhen」xml 属性にタイム ゾーン情報が含まれていないことを検証するにはどうすればよいですか? 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 ファイルでこの Schematron ルールを使用すると、次のようになります。

<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')">

EDIT 2: W3schools の xs:date と 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')) )">
4

1 に答える 1

1

日付または日時のどちらを処理するかはわかりませんが、コードを見ると、両方かもしれません。特定のケースでは、コードが機能しません。

dateTime 仕様が与えられた場合:

dateTime の「語彙空間」は、「-」? という形式の文字の有限長シーケンスで構成されます。yyyy '-' mm '-' dd 'T' hh ':' mm ':' ss ('.' s+)? (zzzzzz)?、ここで ...

詳細については、さらに読むことができます。部分はタイムゾーンであり、次の(zzz)?とおりです(同じソース):

タイムゾーンの字句表現は、次の形式の文字列です: (('+' | '-') hh ':' mm) | 「Z」、ここで...

-2010-03-08Zしたがって、コードは :またはのような date または dateTime では機能しません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,':'))
            )"
于 2012-03-15T16:37:11.993 に答える