2016-06-01 50 views
2

Ich muss ein XSD-Schema mit einer Einschränkung für ein Feld schreiben, um sicherzustellen, dass der Wert des Felds die Teilzeichenfolge FILENAME an keiner Stelle enthält.XML-Schema-Restriktionsmuster für das Nicht zulassen bestimmter Zeichenfolge

Zum Beispiel sind alle der folgenden Aussagen muss ungültig sein:

FILENAME 
ORIGINFILENAME 
FILENAMETEST 
123FILENAME456 

Keiner dieser Werte gültig sein sollte.

In einer regulären Ausdruck-Sprache, die negative Lookahead unterstützt, konnte ich dies tun, indem /^((?!FILENAME).)*$ schreiben, aber die XSD-Mustersprache unterstützt keine negative Lookahead. Wie kann ich eine XSD-Musterbeschränkung mit demselben Effekt wie /^((?!FILENAME).)*$ implementieren?

Ich brauche Muster, weil ich keinen Zugriff auf XSD 1.1 Assertionen habe, die die andere offensichtliche Möglichkeit sind.

Die Frage XSD restriction that negates a matching string behandelt einen ähnlichen Fall, aber in diesem Fall ist die verbotene Zeichenfolge nur als Präfix verboten, was die Überprüfung der Einschränkung erleichtert. Wie kann die Lösung erweitert werden, um den Fall abzudecken, in dem wir alle Stellen innerhalb der Eingabezeichenfolge und nicht nur den Anfang überprüfen müssen?

+2

Mögliches Duplikat [XSD Einschränkung, dass eine passende String negiert] (http://stackoverflow.com/questions/9889206/xsd-restriction-that-negates-a-matching-string) – CSchulz

+0

Nicht, weil in dupliziert meiner case de string FILENAME tritt in jedem Teil der Zeichenfolge nicht nur beim Start auf – Jpff

+1

Ja, es ist ein Duplikat. Jede in den Antworten auf diese Frage beschriebene Methode gilt für diese Frage: Verwenden Sie eine Assertion, um zu bestätigen, dass der Wert FILENAME nicht als Teilzeichenfolge hat, oder schreiben Sie einen regulären Ausdruck, der Zeichenfolgen ohne F entspricht, optional gefolgt von Zeichenfolgen, die F und beginnen Fortfahren mit Nicht-I oder Anfang FI und Fortfahren mit Nicht-L, oder ... –

Antwort

2

OK, das OP hat mich davon überzeugt, dass während the other question mentioned ein überlappendes Thema hat, die Tatsache, dass die verbotene Zeichenfolge an allen Standorten verboten ist, nicht nur als Präfix, Dinge kompliziert genug, um eine separate Antwort zu verlangen, zumindest für die XSD 1.0 Fall. (Ich begann, diese Antwort als Ergänzung zu meiner Antwort auf die andere Frage hinzuzufügen, und es wurde zu groß.)

Es gibt zwei Ansätze, die man hier verwenden kann.

Zuerst in XSD 1.1, eine einfache Behauptung der Form

not(matches($v, 'FILENAME')) 

sollte die Arbeit erledigen.

Zweitens, wenn man gezwungen ist, mit einem XSD 1.0 Prozessor zu arbeiten, braucht man ein Muster, das alle und nur Zeichenfolgen, die die verbotene Teilzeichenfolge (hier 'FILENAME') nicht enthalten.

Eine Möglichkeit, um sicherzustellen, dass das Zeichen "F" nie in der Eingabe auftritt. Das ist zu drastisch, aber es macht den Job: Strings, die nicht das erste Zeichen der verbotenen Zeichenfolge enthalten, enthalten die verbotene Zeichenfolge nicht.

Aber was von Strings, die ein Vorkommen von "F" enthalten? Sie sind in Ordnung, solange kein "F" von der Zeichenfolge "ILENAME" gefolgt wird.

diesem letzten Punkt abstrakter Einlochen, können wir sagen, dass jede gültige Zeichenkette (eine beliebige Zeichenfolge, die nicht die Zeichenfolge ‚Dateiname‘ enthält) kann in zwei Teile unterteilt werden:

  1. Präfix

    die nicht enthält Vorkommen des Zeichens 'F'
  2. null oder mehr Vorkommen von 'F', gefolgt von einem String, der nicht mit 'ILENAME' übereinstimmt und kein 'F' enthält.

Das Präfix ist einfach zu entsprechen: [^F]*.

Die Strings, die mit F beginnen, aber nicht mit 'FILENAME' übereinstimmen, sind etwas komplizierter; genauso wie wir nicht alle Vorkommnisse von "F" ächten wollen, wollen wir auch nicht "FI", "FIL" usw. verbieten - aber jedes Vorkommen einer solchen gefährlichen Kette muss entweder von der Ende der Zeichenfolge, oder durch einen Buchstaben, der nicht mit dem nächsten Buchstaben der verbotenen Zeichenfolge übereinstimmt, oder durch ein anderes 'F', das eine andere Region beginnt, die wir testen müssen. Also für jeden richtigen Präfix der verbotenen Zeichenfolge, schaffen wir einen regulären Ausdruck der Form

$prefix || '([^F' || next-character-in-forbidden-string || ']' 
    || '[^F]*' 

Dann kommen wir alle diese regulären Ausdrücke mit oder Bars.

Das Endergebnis ist in diesem Fall so etwas wie die folgenden (I newlines hier und da eingefügt haben, um es zu erleichtern, lesen, vor der Verwendung, werden sie wieder herausgenommen werden müssen):

[^F]* 
((F([^FI][^F]*)?) 
|(FI([^FL][^F]*)?) 
|(FIL([^FE][^F]*)?) 
|(FILE([^FN][^F]*)?) 
|(FILEN([^FA][^F]*)?) 
|(FILENA([^FM][^F]*)?) 
|(FILENAM([^FE][^F]*)?))* 

Zwei Punkte zu beachten:

  • XSD Reguläre Ausdrücke sind implizit verankert; Wenn Sie dies mit einem nicht verankerten Evaluator für reguläre Ausdrücke testen, werden die korrekten Ergebnisse nicht erzielt.
  • Es mag auf den ersten Blick nicht offensichtlich sein, warum die Alternativen in der Auswahl alle mit [^F]* statt .* enden. Das Nachdenken über die Zeichenfolge 'FEEFIFILENAME' kann helfen. Wir müssen alle Auftreten von "F" überprüfen, um sicherzustellen, dass es nicht von "ILENAME" gefolgt wird.