0

このファイルがある場合: 入力 file1.xml:

<schema>
    <sequence> 
        <nodeA id="a">
            <fruit id="small">
                <orange id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </orange>                           
            </fruit>
            <fruit id="small">
                <apple id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </apple>                           
            </fruit>
            <fruit id="medium">
                <orange id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </orange>                           
            </fruit>
        </nodeA>
        <nodeB id="b">
            <dog id="large">
                <doberman id="x" method="create">
                    <condition>
                        <color>Black</color>
                    </condition>
                </doberman>
            </dog>
        </nodeB>
    </sequence>
</schema>

file2.xml:

<schema>
    <sequence>
        <nodeA id="a">
            <fruit id="small">
                <melon id="x" method="create">
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </melon>
            </fruit>
        </nodeA>
        <nodeB id="b">
            <dog id="small">
                <poodle id="x" method="create">                    
                    <condition>
                        <color>White</color>
                    </condition>
                </poodle>  
            </dog>                
        </nodeB>
    </sequence>
</schema>

連結後: 出力: concate.xml

<schema>
    <sequence>
        <nodeA id="a">
            <fruit id="small">
                <orange id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </orange>                        
            </fruit>
            <fruit id="small">
                <apple id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </apple>                           
            </fruit>
            <fruit id="medium">
                <orange id="x" method="create">                    
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </orange>                           
            </fruit>
            <fruit id="small">
                <melon id="x" method="create">
                    <attributes>
                        <color>Orange</color>
                        <year>2000</year>
                    </attributes>
                </melon>
            </fruit>
        </nodeA>
        <nodeB id="b">
            <dog id="large">
                <doberman id="x" method="create">
                    <condition>
                        <color>Black</color>
                    </condition>
                </doberman>
            </dog>
            <dog id="small">
                <poodle id="x" method="create">                    
                    <condition>
                        <color>White</color>
                    </condition>
                </poodle>  
            </dog>                
        </nodeB>
    </sequence>
</schema>

連結の場合、ファイルの順序に依存するため、file2.xml のノードは file1.xml のノードの下に配置されます (例を参照)。そして、私は最大5つのファイルを持っています。xsl変換のみを使用してこれを達成するにはどうすればよいですか。つまり、xsltは同時に5つのファイルを入力し、1つのファイルを出力しますか?

これは文書構造であり、マージするポイントです:

<schema>
    <sequence> 
        <nodeA id="a">
            <fruit id="small">
                <orange id="x" method="create">                    
                    ...
                </orange>                
            </fruit>
            <fruit id="small">
                ...                          
            </fruit>
            <fruit id="large"> 
                ...                          
            </fruit>

            <!-- we merge below this -->
        </nodeA>

        <nodeB id="b">
            <dog id="large">
                <doberman id="x" method="create">
                    ...
                </doberman>
            </dog>
            <dog id="small">
                <doberman id="x" method="create">
                    ...
                </doberman>
            </dog>
        <!-- we merge below this -->
        </nodeB>

        <somenode id="any">
            ...    
        </somenode>
    </sequence>
</schema>

注: 2 つのファイル入力のみを連結することができない場合は、他のファイルに対していつでも繰り返すことができるため、問題ありません。また、ファイルにはさまざまなノード名 (nodeA、nodeB、SomeNode など) があるため、この問題を一般化できるものが必要です。

xsl1.0 または 2.0 を使用できます。

どうもありがとう。ジョン

4

3 に答える 3

3

@ジョン、より一般的な解決策は次のとおりです。

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http://a.com">
   <xsl:strip-space elements="*" />
   <xsl:output indent="yes" method="xml" />

   <xsl:variable name="to-merge" select="document('input2.xml') | document('input3.xml')"/>

   <xsl:function name="a:id">
      <xsl:param name="ctx"/>
      <xsl:value-of select="concat($ctx/local-name(), $ctx/@id)"/>
   </xsl:function>   

   <xsl:key name="match" match="/schema/sequence/*" use="a:id(.)"/>

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

   <xsl:template match="*[count(. | key('match', a:id(.))) = count(key('match', a:id(.)))]">
    <xsl:copy>
           <xsl:apply-templates select="@* | node()"/>

           <xsl:variable name="id" select="a:id(.)"/>
           <xsl:for-each select="$to-merge">
              <xsl:apply-templates select="key('match', $id)/*"/>
           </xsl:for-each>
    </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

でマージ ポイントkeyを定義し、 でマージ マッチ関数を定義しますa:ida:id関数を述語に入れるだけで、XSLT 1.0 にフォールバックできます。

私の仮定:

  • 「主要な」ドキュメントで変換を実行し、そのto-merge変数でマージをシーケンスします
  • マージする各ドキュメントの同じ場所に一致点が 1 つあります。各ドキュメントのさまざまなポイントからマージするようにソリューションをカスタマイズすることは難しくありません。
  • ノードはlocal-name()およびによって一致します@id
于 2012-05-09T20:08:33.257 に答える
1

ここに別の答えがあります。これは、nodeA と NodeB だけでなく、schema/sequence/* レベルで結合します。

 <?xml version="1.0"?>
 <xsl:stylesheet 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:fn="http://www.w3.org/2005/xpath-functions"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   version="2.0"
   exclude-result-prefixes="xsl xs fn">

 <xsl:output indent="yes" encoding="UTF-8" />
 <xsl:param name="file2" /> <!-- input file1.xml -->
 <xsl:variable name="file1-doc" select="root()" />
 <xsl:variable name="file2-doc" select="document($file2)" />


 <xsl:template  match="/">
  <schema>
   <sequence>
    <xsl:call-template name="union-point">
     <xsl:with-param name="value" select="schema/sequence/*"/>
    </xsl:call-template>
    <xsl:call-template name="union-point">
     <!-- The following predicate excludes all the node names that we
             have already processed in the first call-template.    -->
     <xsl:with-param name="value" select="$file2-doc/schema/sequence/*
      [not (fn:exists($file1-doc/schema/sequence/name()))]
      "/>
    </xsl:call-template>
   </sequence>
  </schema>
 </xsl:template>

 <xsl:template name="union-point">
   <xsl:param name="value"/>
   <xsl:for-each select="$value/name()" >
    <xsl:variable name="node-name" select="."/>
    <xsl:element name="{.}">
 <xsl:attribute name="id">
  <xsl:value-of select="($file1-doc/schema/sequence/*[name()=$node-name]/@id |
                         $file2-doc/schema/sequence/*[name()=$node-name]/@id  )[1]" />
 </xsl:attribute>
     <xsl:apply-templates select="$file1-doc/schema/sequence/*[name()=$node-name]/*" />
     <xsl:apply-templates select="$file2-doc/schema/sequence/*[name()=$node-name]/*" />
    </xsl:element>
   </xsl:for-each>
 </xsl:template>

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

 <xsl:template match="attribute()|text()|comment()|processing-instruction()">
   <xsl:copy/>
 </xsl:template>

 </xsl:stylesheet>

解決策としては、おそらく少し不器用で扱いにくいですが、基本的には機能します。Dimitre Novatchev のような専門家が来て、より適切な代替手段を提供してくれることを願っています。これは私の能力の限界についてです。

* UPDATE 1 * に id 属性を追加しました。

UPDATE 2 結果の出力は次のとおりです。

 <?xml version="1.0" encoding="UTF-8"?>
 <schema>
    <sequence>
       <nodeA id="a">
          <fruit id="small">
                 <orange id="x" method="create">                    
                     <attributes>
                         <color>Orange</color>
                         <year>2000</year>
                     </attributes>
                 </orange>                           
             </fruit>
               <fruit id="small">
                 <apple id="x" method="create">                    
                     <attributes>
                         <color>Orange</color>
                         <year>2000</year>
                     </attributes>
                 </apple>                           
             </fruit>
          <fruit id="medium">
                 <orange id="x" method="create">                    
                     <attributes>
                         <color>Orange</color>
                         <year>2000</year>
                     </attributes>
                 </orange>                           
             </fruit>
          <fruit id="small">
                 <melon id="x" method="create">
                     <attributes>
                         <color>Orange</color>
                         <year>2000</year>
                     </attributes>
                 </melon>
             </fruit>
       </nodeA>
       <nodeB id="b">
          <dog id="large">
                 <doberman id="x" method="create">
                     <condition>
                         <color>Black</color>
                     </condition>
                 </doberman>
             </dog>
          <dog id="small">
                 <poodle id="x" method="create">                    
                     <condition>
                         <color>White</color>
                     </condition>
                 </poodle>  
             </dog>
       </nodeB>
    </sequence>
 </schema>
于 2012-05-08T08:19:57.463 に答える
0

試す:

 <?xml version="1.0"?>
 <xsl:stylesheet 
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:fn="http://www.w3.org/2005/xpath-functions"
   xmlns:xs="http://www.w3.org/2001/XMLSchema"
   version="2.0"
   exclude-result-prefixes="xsl xs fn">

 <xsl:output indent="yes" encoding="UTF-8" />
 <xsl:param name="file2" /> <!-- input file1.xml -->
 <xsl:variable name="file2-doc" select="document($file2)" />

 <xsl:template  match="/">
  <schema>
   <sequence>
    <nodeA id="a">
     <xsl:apply-templates select="schema/sequence/nodeA/*" />
     <xsl:apply-templates select="$file2-doc/schema/sequence/nodeA/*" />
    </nodeA>
    <nodeB id="b">
     <xsl:apply-templates select="schema/sequence/nodeB/*" />
     <xsl:apply-templates select="$file2-doc/schema/sequence/nodeB/*" />
    </nodeB>
   </sequence>
  </schema>
 </xsl:template>

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

 <xsl:template match="attribute()|text()|comment()|processing-instruction()">
   <xsl:copy/>
 </xsl:template>

 </xsl:stylesheet>

file1 をメイン ドキュメント入力にします。file2 のファイル名をパラメータ「file2」として渡します。複数の入力ファイルに対しても同様に拡張します。

于 2012-05-08T02:26:56.380 に答える