0

次の XML ファイルがあります。

<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38">
 <my:Text1></my:Text1>
 <my:Group>
  <my:Text2></my:Text2>
 </my:Group>
</my:myFields>

そしてそれのためのXSD定義:

<xsd:schema targetNamespace="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <xsd:element name="myFields">
  <xsd:complexType>
   <xsd:sequence>
    <xsd:element ref="my:Text1" minOccurs="0"/>
    <xsd:element ref="my:Group" minOccurs="0" maxOccurs="unbounded" />
   </xsd:sequence>
   <xsd:anyAttribute processContents="lax" namespace="http://www.w3.org/XML/1998/namespace"/>
  </xsd:complexType>
 </xsd:element>
 <xsd:element name="Text1" type="xsd:string"/>
 <xsd:element name="Group">
  <xsd:complexType>
   <xsd:sequence>
    <xsd:element ref="my:Text2" minOccurs="0"/>
   </xsd:sequence>
  </xsd:complexType>
  <xsd:element name="Text2" type="xsd:string"/>
 </xsd:element>
</xsd:schema>

XML と XSD に基づく次の XML ファイルを作成したいと思います。

<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38">
 <my:Text1 type="string" minOccurs="0"></my:Text1>
 <my:Group minOccurs="0" maxOccurs="unbounded">
  <my:Text2 type="string" minOccurs="0"></my:Text2>
 </my:Group>
</my:myFields>

.NET プラットフォームでこれを行う最も簡単な方法は何ですか? XSLT 変換を使用することは可能ですか?

4

3 に答える 3

2

このXSLT2.0スタイルシートは、スキーマを調査し、minOccurs、maxOccursタイプの適切な属性値を挿入します。モジュールベースであるため、含めたい他のxsd属性を簡単に拡張できます。デモンストレーションを簡単にするために、スタイルシート内にスキーマを挿入しました。競売では、あなたはそれを外部に残す可能性がありますが。だから、それに応じて。

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38"
  xmlns:l="http://stackoverflow.com/questions/11502608"
  exclude-result-prefixes="xsl xs fn xsd l">
<xsl:output indent="yes"/>

 <xsd:schema targetNamespace="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38"

 ... etc .. INSERT SCHEMA HERE !!!

 </xsd:schema>


<xsl:template match="@*|node()">
 <xsl:copy>
  <xsl:apply-templates select="@*|node()" />
 </xsl:copy>  
</xsl:template>

<xsl:function name="l:xsd-attrib" as="attribute()?">
 <xsl:param name="ele-name" as="xs:string"/>
 <xsl:param name="attri-name" as="xs:string"/>
 <xsl:sequence select="document('')/xsl:stylesheet/xsd:schema
    //(xsd:element[ (substring-after(@ref,'my:')=$ele-name) or (@name=$ele-name)]
    /@*[local-name(self::attribute())=$attri-name])" />
</xsl:function>

<xsl:template name="l:emit-xsd-attri">
 <xsl:param name="my-node" as="element()" />
 <xsl:param name="attri-name" as="xs:string" />  
  <xsl:variable name="ele" select="local-name( $my-node)" />
  <xsl:if test="l:xsd-attrib( $ele, $attri-name)">
   <xsl:attribute name="{$attri-name}"><xsl:value-of select="
     for $l in l:xsd-attrib( $ele, $attri-name) return
      if (contains( $l, ':')) then substring-after( $l, ':') else $l" />
    </xsl:attribute>
  </xsl:if>
</xsl:template> 

<xsl:template match="my:*"> 
 <xsl:copy>
  <xsl:apply-templates select="@*" />

  <xsl:call-template name="l:emit-xsd-attri">
   <xsl:with-param name="my-node" select="." />
   <xsl:with-param name="attri-name" select="'minOccurs'" />  
  </xsl:call-template>

  <xsl:call-template name="l:emit-xsd-attri">
   <xsl:with-param name="my-node" select="." />
   <xsl:with-param name="attri-name" select="'maxOccurs'" />  
  </xsl:call-template>

  <xsl:call-template name="l:emit-xsd-attri">
   <xsl:with-param name="my-node" select="." />
   <xsl:with-param name="attri-name" select="'type'" />  
  </xsl:call-template>

  <xsl:apply-templates select="node()" />
 </xsl:copy>  
</xsl:template>

</xsl:stylesheet>
于 2012-07-16T13:50:04.940 に答える
2

の修正されたスキーマが与えられた場合

<xsd:schema targetNamespace="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="myFields">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="my:Text1" minOccurs="0"/>
                <xsd:element ref="my:Group" minOccurs="0" maxOccurs="unbounded" />
            </xsd:sequence>
            <xsd:anyAttribute processContents="lax" namespace="http://www.w3.org/XML/1998/namespace"/>
        </xsd:complexType>
    </xsd:element>
    <xsd:element name="Text1" type="xsd:string"/>
    <xsd:element name="Text2" type="xsd:string"/>
    <xsd:element name="Group">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="my:Text2" minOccurs="0"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

指定した XML 入力、このスタイルシート

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ext="http://exslt.org/common" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38">
<xsl:output method="xml" indent="yes"/>
    <xsl:variable name="schema" select="document('so.xsd')//xsd:schema"/>

<xsl:template match="/">
     <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
</xsl:template>

<xsl:template match="my:*">
    <xsl:variable name="name" select="name()"></xsl:variable>
    <xsl:variable name="basename" select="substring-after($name,':')"></xsl:variable>
    <xsl:copy>
        <xsl:variable name="types" select="$schema//xsd:element[@name=$basename]/@type"/>
        <xsl:if test="$types">
            <xsl:attribute name="type">
                <xsl:value-of select="$types"/>
            </xsl:attribute>
        </xsl:if>
        <xsl:for-each select="$schema//xsd:element[@ref=$name]/@*[name()!='ref']">
            <xsl:attribute name="{name()}">
                <xsl:value-of select="."/>
            </xsl:attribute>
        </xsl:for-each>
        <xsl:apply-templates select="*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="node()|@*">
    <xsl:copy><xsl:apply-templates select="node()|@*" /></xsl:copy>
</xsl:template>

</xsl:stylesheet>

次の出力が生成されます。これは、あなたが望んでいたものだと思います。

<?xml version="1.0" encoding="utf-8"?>
<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-05-05T12:20:38" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003">
   <my:Text1 type="xsd:string" minOccurs="0"/>
   <my:Group minOccurs="0" maxOccurs="unbounded">
      <my:Text2 type="xsd:string" minOccurs="0"/>
   </my:Group>
</my:myFields>

それが行うことは、スキーマをドキュメントとしてロードし、各要素について、そのタイプの要素のドキュメントを検索し、その属性をコピーしてから、正しいタイプの参照を探してそれらの要素もコピーすることです。

唯一の問題は、適切なセクションを探してスキーマを実際にたどらず、名前でアドレス指定するだけであることです。小さなスキーマの場合、おそらくほとんどの場合は正しいですが、場合によっては問題が発生することがあります。しかし、現時点であなたが示しているものについてはうまくいくでしょう。

于 2012-07-16T13:15:50.677 に答える
0

XMLインスタンスドキュメントをスキーマに対して検証すると、必要なすべての情報などを含むPSVI(スキーマ検証後のインスタンス)が生成されます。唯一の問題は、この情報を実際にどのように入手するかです。これは、使用するツールによって異なります。たとえば、スキーマバリデーターとしてXercesを使用する場合、スキーマプロセッサによってインスタンスに追加されたPSVIアノテーションを公開するためのAPIがあります。

于 2012-07-16T14:19:32.097 に答える