-2

xml スキーマから通常の exp を取得するには? xml スキーマには明確な正規表現があることがわかっています。しかし、それを実現する方法は?(たとえば、通常の exp を取得するプログラムをコーディングします)。

complexType のみを考慮してください。例: xsd には、次のものがあります。

<xs:element name="letter">
  <xs:complexType mixed="true">
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="orderid" type="xs:positiveInteger"/>
      <xs:element name="shipdate" type="xs:date"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

または:

<xs:complexType name="lettertype" mixed="true">
  <xs:sequence>
    <xs:element name="name" type="xs:string"/>
    <xs:element name="orderid" type="xs:positiveInteger"/>
    <xs:element name="shipdate" type="xs:date"/>
  </xs:sequence>
</xs:complexType>

検索シーケンスは "," を意味するため、結果は "letter (name,orderid,shipdate)" 結果は name regex です。

別の例: (xsd にこれがある場合:)

<xs:complexType name="request">
<xs:all>
  <xs:element name="url" type="xs:string"/>
  <xs:element name="component" type="xs:string"/>
  <xs:element name="action" type="xs:string" minOccurs="0"/>
  <xs:element name="params" type="varList" minOccurs="0"/>
  <xs:element name="session" type="varList" minOccurs="0"/>
  <xs:element name="cgi-data" type="varList" minOccurs="0"/>
</xs:all>

complexType の名前が「request」であることを意味します。。。の関係は「すべて」(「すべて」を & で表現すると)すべて「&」なので、結果は「request url&component&action¶ms&session&cgi-data」となります。

この機能を実現するプログラムのコーディングを手伝ってくれる人はいますか? またはアルゴリズムを教えてください。

プログラムをコーディングしましたが、あまりにもバグが多く、論理的に間違っています。これが私のプログラムです:

#include<stdio.h> 
#include<string.h>
#include <stdlib.h>
#include<io.h> 
#define MatchMaxLen 69500
void process(char *result,char *str,char *str2,FILE* fp1)
{
if(strstr(str2,"complexType>")) fgets(str2,3000,fp1);
        //strcat(str,   str2);
    char c[5],*pem;
    int m=0;   if(!strstr(str2,"xs:sequence")&&!strstr(str2,"xs:choice")&&!strstr(str2,"xs:all")) return;
    if(strstr(str,"element name=\""))
        {
            pem=strstr(str,"element name=\"")+strlen("element name=\"");

            while(*pem!='\"')*result++=*pem++;//put element name in purec

            *result++=' ';
        }   
    if(strstr(str2,"xs:sequence")) {*result++='(';c[m++]=',';}
    if(strstr(str2,"xs:choice")) {*result++='(';c[m++]='|';}
    if(strstr(str2,"all")) {*result++='(';c[m++]='&';}
    fgets(str2,3000,fp1);
    while(!(strstr(str2,"sequence>")||strstr(str2,"choice>")||strstr(str2,"all>")))
        {
            if(str2,"complexType>") process(result,str,str2,fp1);
    if(strstr(str2,"element name=\""))
    {
    pem=strstr(str2,"element name=\"");
    pem=pem+strlen("element name=\"");
    }
    if(strstr(str2,"element ref=\""))
    {
    pem=strstr(str2,"element ref=\"");
    pem=pem+strlen("element ref=\"");
    }
    while(*pem!='\"') *result++=*pem++;

    char *pmax,*pmin;
    pmin=strstr(str2,"minOccurs=\"");
    pmin=pmin+strlen("minOccurs=\"");
    pmax=strstr(str2,"maxOccurs=\"");
    pmax=pmax+strlen("maxOccurs=\"");
    if(strstr(str2,"minOccurs")&&strstr(str2,"maxOccurs"))
    {
        if(*pmax=='1'&&*pmin=='0')
        {
        *result++=')';
        *result++='?';
        }
    if(*pmax=='u'&&*pmin=='0')
        {   
        *result++=')';
        *result++='*';
        }
    if(*pmax=='u' && *pmin=='1')
        {
        *result++=')';
        *result++='+';
        }
    *result++=c[m-1];
    }

    fgets(str2,3000,fp1);}
    m--;
}

void main()
{
char type[100][20];
char name[100][20];
char res[3000];
char *result=res;
int flag=0;
char *str, *str2,*psp;
char destfname[20];
char *path="E:\\study\\research\\summer\\program\\*.xsd";/*use this when needed in future extension.Well, been used currently*/
char path1[]="E:\\study\\research\\summer\\program\\";
int len;
FILE *fp1,*fp2; 
char string[MatchMaxLen];
char string2[3000];
struct _finddata_t   ffblk;
long done= _findfirst(path,&ffblk);  
do{ /*sprintf(filename,"dtd%d.dtd",i); 
In the future if the filename is not regular or we don't know the exact numbersome day, 
you may need function like _findnext,_findfirst.Well, currently being used*/
strcat(path1,ffblk.name);
if ((fp1=fopen(path1,"r"))==NULL)
{ /* read source file*/
        printf("cannot open file\n");
        exit(0);
}
sprintf(destfname,"IncludeNamexsdRe%s.txt",ffblk.name);
if((fp2=fopen(destfname,"w"))==NULL)
{ /* destination file*/
        printf("cannot open file\n"); 
        exit(0);
}   
char *pem;
int j(0);
int i(0);
while (fgets(string,MatchMaxLen,fp1))
{//first while's purpose is to create the map of name and type      
str=string;
if(!strstr(str,"element name")) continue;// the thing u need to process
i++;
pem=strstr(str,"element name");
pem=pem+strlen("element name=")+1;//pem: pointer of the element name
while(*pem!='\"')//while not the end point """
{
name[i][j++]=*pem++;//put the element name to the name[][]
}
name[i][j]='\0';
if(!(psp=strstr(string,"type="))) continue;
memccpy(type[i],psp+6,'\"',22); 
}
rewind(fp1);//normal process, here we go
char purecomplex[20];
char *purec=purecomplex;
char ctype[20];
char *cotype=ctype;
while (fgets(string,MatchMaxLen,fp1))
{   
        if( strlen( string ) == 0 ) 
            continue;
    str=string;
    if (str == NULL) 
        continue; 
    if( strlen( string ) == 1 ) continue;   
    //printf("%s",string);

    str2=string2;
    if(strstr(str,"<!--")) 
    {
        while(!strstr(str,"-->"))
        {
        fgets(str2,3000,fp1);
        strcat(str, str2);
    //delete useless char
    //printf("%s\n",str2); 
        }
    continue;
    }
    if(!(pem=strstr(str,"element name=\""))&&!strstr(str,"complexType name=")) continue;

    /*while(match(str))
    {*/
        fgets(str2,3000,fp1);
        if(strstr(str2,"annotation>"))
        {
            do{ fgets(str2,3000,fp1);}while(!strstr(str2,"</xs:annotation>"));
            fgets(str2,3000,fp1);
        }

        if(strstr(str,"complexType name=\""))
        {
            char* pt;
            pt=strstr(str,"complexType name=\"")+strlen("complexType name=\"");
    //if(strstr(str,"element name=\"")) pt=strstr(str,"element name=\"")+strlen("element name=\"");

            while(*pt!='"') *result++=*pt++;//if has complextype name, put it in cotype

            *result++=' ';
        }
        process(result,str,str2,fp1);
    }//}
    *result='\0';
    fputs(res,fp2 );
    //fputc('\n',fp2 );

    //printf("%s\n",ffblk.name);
    printf("2===%s\n",string);
    fclose(fp1);
    fclose(fp2);
}while(!_findnext(done,&ffblk));

_findclose(done);         

}

この機能を実現するプログラムのコーディングを手伝ってくれる人はいますか? またはアルゴリズムを教えてください。

4

1 に答える 1

1

実際、すべての XSD コンテンツ モデルは QNames を介して正規表現に変換できるため、この XSD を文書化の目的で、または複雑な型についてより便利に推論する目的で表示したい場合があるため、この質問はそれほど奇妙でもオフでもありません-一部の回答者は疑う傾向があるようです。少なくとも、必ずしも空想的またはオフベースである必要はありません。

しかし、この問題を解決したい理由と、その結果に対して何をしたいのかについて、もう少し背景を説明していただければ、この問題の解決に熱心に取り組みやすくなります。スキーマに対してドキュメントを検証する場合は、通常、既製のバリデーターを使用する方が適切です。(市販のツールを使用する代わりに、独自のバリデーターを作成するのはいつでも楽しいものですが、独自の XSD バリデーターを作成できる立場にある人は、XSD コンテンツ モデルを正規表現のような表記法に変換する手助けを必要としません。それはあなたが目指しているものではないと推測してください。)

しかし、十分な警告です。何らかの理由で本当にこれを実行したい場合は、XSLT のような適切な XML 指向の言語を使用すれば、そのタスクは概念的に簡単です。一般的なアプローチを説明するために、XSLT プログラムを追加します。単純なケースでは (私がテストした限りでは) 正しく動作しますが、実際のスキーマでの作業に必要な簿記や手間のかかる詳細はすべて無視されます。複合型拡張、複数の名前空間のスキーマ ドキュメント、または別の複合型にローカルな要素に対して定義された複合型を処理しようとはしません。また、サンプルと同様に、名前付き正規表現の名前は、変換される複合型またはそれを囲む要素宣言のいずれかから取得されます。つまり、スキーマに同じローカル名の型と要素がある場合、問題が発生します。

<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                >

  <xsl:output method="text"/>

  <!--* Ignore anything that looks complicated *-->
  <xsl:template match="xsd:attribute 
                       | xsd:attributeGroup
                       | xsd:group
                       | xsd:schema/xsd:element[@type]
                       | xsd:notation
                       | xsd:annotation
                       "/>

  <!--* Ignore text nodes (otherwise the output will be
      * inundated with whitespace) *-->
  <xsl:template match="text()"/>

  <!--* Top-level elements with local complex types; those
      * we want to handle.
      *-->
  <xsl:template match = "xsd:schema/xsd:element[xsd:complexType]">
    <xsl:apply-templates/>
  </xsl:template>

  <!--* Aha!  A complex type whose content model we want to turn 
      * into a regular expression 
      *-->
  <xsl:template match = "xsd:element/xsd:complexType
                         [xsd:sequence | xsd:choice | xsd:all]">
    <!--* write out the name for the named regex *-->
    <xsl:value-of select="concat('&#xA;&#xA;',
                          @name, parent::xsd:element/@name, 
                          ' ')"/>
    <!--* write out the regex *-->
    <xsl:apply-templates/>
  </xsl:template>

  <!--* Simple recursive case:  we encounter a model group. *-->
  <xsl:template match = "xsd:sequence|xsd:choice|xsd:all">
    <!--* Parenthesize the group and handle its children. *-->
    <xsl:text>(</xsl:text>
    <xsl:apply-templates/>
    <xsl:text>)</xsl:text>

    <!--* Append *, ?, +, or {min, max}. *-->
    <xsl:call-template name="occurrence-indicator"/>

    <!--* If our parent has further children, 
        * append the appropriate connector. *-->
    <xsl:call-template name="connector"/>
  </xsl:template>

  <!--* An element in a content model. *-->
  <xsl:template match = "xsd:element[ancestor::xsd:complexType]">
    <!--* Write out the element's name.  We're lazy so 
        * we don't bother with a QName for a local element.
        * Also, we don't recur. *-->
    <xsl:value-of select="concat(@ref, @name)"/>

    <!--* Handle occurrence indicator and connect
        * just as for groups. *-->
    <xsl:call-template name="occurrence-indicator"/>
    <xsl:call-template name="connector"/>
  </xsl:template>


  <!--* Emit the appropriate occurrence indicator for
      * a group or element.
      * Use {min,max}, {min,}, or {n} notation for 
      * non-standard occurrence counts.
      *-->
  <xsl:template name="occurrence-indicator">
    <xsl:choose>
      <xsl:when test="(@minOccurs='1' or not(@minOccurs)) 
                      and 
                      (@maxOccurs='1' or not(@maxOccurs))">
        <xsl:text></xsl:text>
      </xsl:when>
      <xsl:when test="@minOccurs='0' 
                      and 
                      (@maxOccurs='1' or not(@maxOccurs))">
        <xsl:text>?</xsl:text>
      </xsl:when>
      <xsl:when test="@minOccurs='0' and @maxOccurs='unbounded'">
        <xsl:text>*</xsl:text>
      </xsl:when>
      <xsl:when test="(@minOccurs='1' or not(@minOccurs)) 
                      and 
                      @maxOccurs='unbounded'">
        <xsl:text>+</xsl:text>
      </xsl:when>
      <xsl:when test="@minOccurs=@maxOccurs">
        <xsl:value-of select="concat('{', @minOccurs,'}')"/>
      </xsl:when>
      <xsl:when test="@maxOccurs='unbounded'">
        <xsl:value-of select="concat('{', @minOccurs,',}')"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="concat('{', 
                              @minOccurs,
                              ',',
                              @maxOccurs,
                              '}')"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="connector">
    <!--* Emit the appropriate connector, if we need one. *-->
    <xsl:if test="following-sibling::*[self::xsd:sequence 
                  | self::xsd:choice 
                  | self::xsd:all 
                  | self::xsd:element]">
      <xsl:choose>
        <xsl:when test="parent::xsd:sequence">
          <xsl:text>, </xsl:text>
        </xsl:when>
        <xsl:when test="parent::xsd:choice">
          <xsl:text> | </xsl:text>
        </xsl:when>
        <xsl:when test="parent::xsd:all">
          <xsl:text> &amp; </xsl:text>
        </xsl:when>
      </xsl:choose>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

なんらかの理由で XSLT の問題を処理できない、または処理しない場合は、通常の深さ優先のツリー (具体的にはスキーマ ドキュメントのコンテンツ モデル)、適切なブラケットと演算子を適切なタイミングで発行します。

  • 各要素で、適切な QName を発行します。
  • 各グループで、左括弧を発行し、子を処理してから、右括弧を発行します。
  • 各式 (要素またはグループ) の後に、オカレンス インジケーターを出力します: *、+、?、空の文字列、または 、 、または などのカウント{4}演算{2,}{0,4}
  • 任意の 2 つの兄弟式の間 (つまり、右の兄弟を持つ各式の後) に、適切なコネクタ (カンマ、アンパサンド、またはバー) を出力します。

これが役立つことを願っています。

于 2012-08-19T19:20:50.187 に答える