2

親と子の関係に基づいて、xml を別の xml に変換する必要があります。

以下は私のソースxmlです

<FIXML>
    <Header>
        <RequestID>ReqID8942</RequestID>
    </Header>
    <Body>
     <Data>
      <LimitDetails>
        <LimitRefNo>L1</LimitRefNo>
        <LimitClassification>ROOT</LimitClassification>
        <ParentLimitRefNo></ParentLimitRefNo>
        <ApprovedLimit>100.0</ApprovedLimit>
      </LimitDetails>
      <LimitDetails>
        <LimitRefNo>L2</LimitRefNo>
        <LimitClassification>ClASSIFICATION1</LimitClassification>
        <ParentLimitRefNo>L1</ParentLimitRefNo>
        <ApprovedLimit>200.0</ApprovedLimit>
      </LimitDetails>
      <LimitDetails>
        <LimitRefNo>L3</LimitRefNo>
        <LimitClassification>CLASSIFICATION2</LimitClassification>
        <ParentLimitRefNo>L2</ParentLimitRefNo>
        <ApprovedLimit>300.0</ApprovedLimit>
      </LimitDetails>
      <LimitDetails>
        <LimitRefNo>L4</LimitRefNo>
        <LimitClassification>CLASSIFICATION3</LimitClassification>
        <ParentLimitRefNo>L3</ParentLimitRefNo>
        <ApprovedLimit>400.0</ApprovedLimit>
      </LimitDetails>
      </Data>
   </Body>
</FIXML>

ここで、子の制限は、ParentLimitRefNo に基づく親の制限を参照します。親制限は、ParentLimitRefNo が空である制限です。

以下は、ソースxmlに基づいて作成する必要があるxmlです。

<FIXML>
    <Header>
        <RequestID>ReqID8942</RequestID>
    </Header>
    <Body>
     <Data>
      <LimitDetails>
        <Limit>
           <LimitRefNo>L1</LimitRefNo>
           <LimitClassification>ROOT</LimitClassification>
           <ParentLimitRefNo></ParentLimitRefNo>
           <ApprovedLimit>100.0</ApprovedLimit>
           <SubLimit>
             <LimitRefNo>L2</LimitRefNo>
             <LimitClassification>ClASSIFICATION1</LimitClassification>
             <ParentLimitRefNo>L1</ParentLimitRefNo>
             <ApprovedLimit>200.0</ApprovedLimit>
         <SubLimit>
           <LimitRefNo>L3</LimitRefNo>
               <LimitClassification>CLASSIFICATION2</LimitClassification>
               <ParentLimitRefNo>L2</ParentLimitRefNo>
               <ApprovedLimit>300.0</ApprovedLimit>
           <SubLimit>
              <LimitRefNo>L4</LimitRefNo>
              <LimitClassification>CLASSIFICATION3</LimitClassification>
                  <ParentLimitRefNo>L3</ParentLimitRefNo>
                  <ApprovedLimit>400.0</ApprovedLimit> 
           </SubLimit>
        </SubLimit>
       </SubLimit>
      </Limit>
    </LimitDetails>
  </Data>
</Body>

前もって感謝します。

4

2 に答える 2

1

このXSLT2.0変換(XSLT 1.0への変換が簡単)

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

 <xsl:key name="kLD" match="LimitDetails" use="ParentLimitRefNo"/>

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

 <xsl:template match="Data">
  <Data>
    <LimitDetails>
        <xsl:apply-templates
        select="LimitDetails[not(ParentLimitRefNo/node())]"/>
    </LimitDetails>
  </Data>
 </xsl:template>

 <xsl:template match="LimitDetails">
  <xsl:variable name="vSuf" select=
    "if(ParentLimitRefNo/text())
       then 'Sub'
       else ()
    "/>

  <xsl:element name="{$vSuf}Limit">
    <xsl:apply-templates select="node()|key('kLD', LimitRefNo)"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

提供されたXMLドキュメントに適用した場合

<FIXML>
    <Header>
        <RequestID>ReqID8942</RequestID>
    </Header>
    <Body>
        <Data>
            <LimitDetails>
                <LimitRefNo>L1</LimitRefNo>
                <LimitClassification>ROOT</LimitClassification>
                <ParentLimitRefNo></ParentLimitRefNo>
                <ApprovedLimit>100.0</ApprovedLimit>
            </LimitDetails>
            <LimitDetails>
                <LimitRefNo>L2</LimitRefNo>
                <LimitClassification>ClASSIFICATION1</LimitClassification>
                <ParentLimitRefNo>L1</ParentLimitRefNo>
                <ApprovedLimit>200.0</ApprovedLimit>
            </LimitDetails>
            <LimitDetails>
                <LimitRefNo>L3</LimitRefNo>
                <LimitClassification>CLASSIFICATION2</LimitClassification>
                <ParentLimitRefNo>L2</ParentLimitRefNo>
                <ApprovedLimit>300.0</ApprovedLimit>
            </LimitDetails>
            <LimitDetails>
                <LimitRefNo>L4</LimitRefNo>
                <LimitClassification>CLASSIFICATION3</LimitClassification>
                <ParentLimitRefNo>L3</ParentLimitRefNo>
                <ApprovedLimit>400.0</ApprovedLimit>
            </LimitDetails>
        </Data>
    </Body>
</FIXML>

必要な正しい結果を生成します

<FIXML>
   <Header>
      <RequestID>ReqID8942</RequestID>
   </Header>
   <Body>
      <Data>
         <LimitDetails>
            <Limit>
               <LimitRefNo>L1</LimitRefNo>
               <LimitClassification>ROOT</LimitClassification>
               <ParentLimitRefNo/>
               <ApprovedLimit>100.0</ApprovedLimit>
               <SubLimit>
                  <LimitRefNo>L2</LimitRefNo>
                  <LimitClassification>ClASSIFICATION1</LimitClassification>
                  <ParentLimitRefNo>L1</ParentLimitRefNo>
                  <ApprovedLimit>200.0</ApprovedLimit>
                  <SubLimit>
                     <LimitRefNo>L3</LimitRefNo>
                     <LimitClassification>CLASSIFICATION2</LimitClassification>
                     <ParentLimitRefNo>L2</ParentLimitRefNo>
                     <ApprovedLimit>300.0</ApprovedLimit>
                     <SubLimit>
                        <LimitRefNo>L4</LimitRefNo>
                        <LimitClassification>CLASSIFICATION3</LimitClassification>
                        <ParentLimitRefNo>L3</ParentLimitRefNo>
                        <ApprovedLimit>400.0</ApprovedLimit>
                     </SubLimit>
                  </SubLimit>
               </SubLimit>
            </Limit>
         </LimitDetails>
      </Data>
   </Body>
</FIXML>

説明

  1. IDルールの使用と変更。

  2. キーを使用して、LimitDetailsからのすべての論理子を指定しますLimitRefNo


II。XSLT 1.0ソリューション

これは、上記の変換をXSLT 1.0にほぼ機械的に変換したものであり、変数の定義のみ$vSufが異なります。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kLD" match="LimitDetails" use="ParentLimitRefNo"/>

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

 <xsl:template match="Data">
  <Data>
    <LimitDetails>
        <xsl:apply-templates
        select="LimitDetails[not(ParentLimitRefNo/node())]"/>
    </LimitDetails>
  </Data>
 </xsl:template>

 <xsl:template match="LimitDetails">
  <xsl:variable name="vSuf" select=
  "concat('',
          substring('Sub',1 div boolean(ParentLimitRefNo/text()))
         )"/>

  <xsl:element name="{$vSuf}Limit">
    <xsl:apply-templates select="node()|key('kLD', LimitRefNo)"/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

同じXMLドキュメント(上記)に適用すると、同じ正しい結果が生成されます。

于 2012-10-21T16:30:48.253 に答える
1

キーの使用は確かにより洗練されていますが(Dimitre Novatchevsソリューションを参照)、これは構造に必要な変更を考慮に入れています(たとえば、名前<LimitDetails />を変更してタグ<SubLimit />を配置します)。<Limit />

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

<xsl:template match="Data">
    <xsl:copy>
        <LimitDetails>
            <Limit>
                <xsl:apply-templates select=".//LimitDetails[./ParentLimitRefNo='']" />
            </Limit>
        </LimitDetails>
    </xsl:copy>
</xsl:template>

<xsl:template match="LimitDetails">
    <xsl:variable name="LimitRefNo" select="./LimitRefNo" />
    <xsl:apply-templates select="@*|node()" />
    <xsl:if test="../LimitDetails[./ParentLimitRefNo = $LimitRefNo]">
    <SubLimit>
        <xsl:apply-templates select="../LimitDetails[./ParentLimitRefNo = $LimitRefNo]" />
    </SubLimit>
    </xsl:if>
</xsl:template>
</xsl:transform>

または、キーを使用したDimitreのソリューションの変更として:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kLD" match="LimitDetails" use="ParentLimitRefNo"/>

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

 <xsl:template match="Data">
  <Data>
    <LimitDetails>
      <Limit>
      <xsl:apply-templates select="LimitDetails[not(ParentLimitRefNo/node())]"/>
      </Limit>
    </LimitDetails>
  </Data>
 </xsl:template>

 <xsl:template match="LimitDetails">
  <xsl:apply-templates />
  <xsl:if test="key('kLD', LimitRefNo)">
  <SubLimit>
    <xsl:apply-templates select="key('kLD', LimitRefNo)"/>
  </SubLimit>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>
于 2012-10-21T16:41:05.707 に答える