在给定节点之后包含兄弟节点

时间:2011-10-25 17:36:28

标签: xml xslt

我需要帮助在以下xml中的节点ExtraInfo中的节点FirstName之后封闭一些兄弟节点:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BatchMember>
    <Member>
        <FirstName>MICHAEL             </FirstName>
        <Books>
            <Fiction>1</Fiction>
            <ChildrensBooks> </ChildrensBooks>
        </Books>
        <Stationery>
            <Art> </Art>
            <Writing> </Writing>
        </Stationery>
        <CardsGifts>1</CardsGifts>
        <ROINI>1</ROINI>
        <Signed>1</Signed>
        <Date>2011-10-04</Date>
    </Member>
    <Member>
        <FirstName>JOHN              </FirstName>
        <Books>
            <Fiction>1</Fiction>
            <ChildrensBooks> </ChildrensBooks>
        </Books>
        <Stationery>
            <Art>1</Art>
            <Writing> </Writing>
        </Stationery>
        <CardsGifts>1</CardsGifts>
        <ROINI> </ROINI>
        <Signed>1</Signed>
        <Date>2011-10-04</Date>
    </Member>
</BatchMember>

我使用了以下xsl文件:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ex="http://exslt.org/dates-and-times"  extension-element-prefixes="ex">
<xsl:strip-space elements="FirstName Surname Add1 Add2 City Email"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="BatchMember" >
        <xsl:variable name="newline">
            <xsl:text>
            </xsl:text>
        </xsl:variable>


        <Batch>
            <xsl:element name="Version" >1.0</xsl:element>
            <xsl:copy>
                <xsl:apply-templates />
            </xsl:copy>
        </Batch>
    </xsl:template>

    <xsl:strip-space elements="*"/>

    <xsl:key name="kFollowing" match="FirstName"  use="generate-id(preceding-sibling::*[not(self::b)][1])"/>



    <xsl:template match="FirstName[not(preceding-sibling::*[1][self::FirstName])]">
        <ExtraInfo>
            <xsl:copy-of select="key('kFollowing', generate-id(preceding-sibling::*[1]))"/>
        </ExtraInfo>
    </xsl:template>

     <xsl:template match="FirstName"/>

      <xsl:param name="true-text" select="'True'"/>
      <xsl:param name="false-text" select="'False'"/>

        <xsl:template match="FirstName">

        </xsl:template>   
      <xsl:template match="Books">
        <Category>
            <Name>Books</Name>        
                    <xsl:choose>
                        <xsl:when test="Fiction = 1">
                            <Fiction>
                                <xsl:value-of select="$true-text"/>
                            </Fiction>
                        </xsl:when>
                        <xsl:otherwise>
                            <Fiction>
                                <xsl:value-of select="$false-text"/>
                            </Fiction>
                        </xsl:otherwise>
                    </xsl:choose>
                    <xsl:choose>
                        <xsl:when test="ChildrensBooks = 1">
                            <ChildrensBooks>
                                <xsl:value-of select="$true-text"/>
                            </ChildrensBooks>
                        </xsl:when>
                        <xsl:otherwise>
                            <ChildrensBooks>
                                <xsl:value-of select="$false-text"/>
                            </ChildrensBooks>
                        </xsl:otherwise>
                    </xsl:choose>
        </Category>
</xsl:template>  
<xsl:template match="Stationery">
        <Category>
            <Name>Stationery</Name>
                    <xsl:choose>
                        <xsl:when test="Art = 1">
                            <Art>
                                <xsl:value-of select="$true-text"/>
                            </Art>
                        </xsl:when>
                        <xsl:otherwise>
                            <Art>
                                <xsl:value-of select="$false-text"/>
                            </Art>
                        </xsl:otherwise>
                    </xsl:choose>
                    <xsl:choose>
                        <xsl:when test="Writing = 1">
                            <Writing>
                                <xsl:value-of select="$true-text"/>
                            </Writing>
                        </xsl:when>
                        <xsl:otherwise>
                            <Writing>
                                <xsl:value-of select="$false-text"/>
                            </Writing>
                        </xsl:otherwise>
                    </xsl:choose>
        </Category>
  </xsl:template>

    <xsl:template match="CardsGifts">
      </xsl:template>
</xsl:stylesheet>

产生了以下结果:

  <?xml version="1.0" ?> 
- <Batch>
  <Version>1.0</Version> 
- <BatchMember>
- <Member>
- <ExtraInfo>
  <FirstName>MICHAEL</FirstName> 
  <FirstName>JOHN</FirstName> 
  </ExtraInfo>
- <Category>
  <Name>Books</Name> 
  <Fiction>True</Fiction> 
  <ChildrensBooks>False</ChildrensBooks> 
  </Category>
- <Category>
  <Name>Stationery</Name> 
  <Art>False</Art> 
  <Writing>False</Writing> 
  </Category>
  <ROINI>1</ROINI> 
  <Signed>1</Signed> 
  <Date>2011-10-04</Date> 
  </Member>
- <Member>
- <ExtraInfo>
  <FirstName>MICHAEL</FirstName> 
  <FirstName>JOHN</FirstName> 
  </ExtraInfo>
- <Category>
  <Name>Books</Name> 
  <Fiction>True</Fiction> 
  <ChildrensBooks>False</ChildrensBooks> 
  </Category>
- <Category>
  <Name>Stationery</Name> 
  <Art>True</Art> 
  <Writing>False</Writing> 
  </Category>
  <ROINI /> 
  <Signed>1</Signed> 
  <Date>2011-10-04</Date> 
  </Member>
  </BatchMember>
  </Batch>

这是我要求的结果:

<?xml version="1.0"?>
<BatchMember>
<Version>1.0</Version>
    <Member>
        <FirstName>MICHAEL</FirstName>
        <ExtraInfo>
            <Category>
                <Name>Books</Name>
                    <attribute>
                        <Name>Fiction</Name>
                        <Value>True</Value>
                    </attribute>
                    <attribute>
                        <Name>Children's</Name>
                        <Value>False</Value>
                    </attribute>
            </Category>
            <Category>
                <Name>Stationery</Name>
                    <attribute>
                        <Name>Art</Name>
                        <Value>False</Value>
                    </attribute>
                    <attribute>
                        <Name>Writing</Name>
                        <Value>False</Value>
                    </attribute>
            </Category>
        </ExtraInfo>
    </Member>
    <Member>
        <FirstName>JOHN</FirstName>
        <ExtraInfo>
            <Category>
                <Name>Books</Name>
                    <attribute>
                        <Name>Fiction</Name>
                        <Value>True</Value>
                    </attribute>
                    <attribute>
                        <Name>Children's</Name>
                        <Value>False</Value>
                    </attribute>
            </Category>
            <Category>
                <Name>Stationery</Name>
                    <attribute>
                        <Name>Art</Name>
                        <Value>True</Value>
                    </attribute>
                    <attribute>
                        <Name>Writing</Name>
                        <Value>False</Value>
                    </attribute>
            </Category>
        <ExtraInfo>
    </Member>
</BatchMember>

我做错了什么?

问候

杰夫。

1 个答案:

答案 0 :(得分:0)

我认为你的XSLT可能过于复杂。例如,您不一定需要 xsl:key

您可以做的是,当您匹配成员元素时,为 FirstName 元素添加一些定制编码以进行复制,然后继续匹配所有子元素

<xsl:template match="Member">
   <xsl:copy>
      <xsl:copy-of select="FirstName"/>
      <ExtraInfo>
         <xsl:apply-templates />
      </ExtraInfo>
   </xsl:copy>
</xsl:template>

但是,您需要一个空模板来再次匹配FirstName元素,以避免输出两次

<xsl:template match="FirstName" />

您还需要为图书固定元素添加匹配模板,以便对这些元素进行特殊处理

<xsl:template match="Books|Stationery">
   <Category>
      <Name>
         <xsl:value-of select="local-name()"/>
      </Name>
      <xsl:apply-templates select="*" mode="Attributes"/>
   </Category>
</xsl:template>

您还需要一个模板来处理 Book 固定元素的子项。我并不是100%确定你想要做什么,但是在预期的输出中,看起来你想将它们转换为属性元素。

这是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ex="http://exslt.org/dates-and-times" extension-element-prefixes="ex">
   <xsl:strip-space elements="FirstName Surname Add1 Add2 City Email"/>

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

   <xsl:template match="BatchMember">
      <Batch>
         <Version>1.0</Version>
         <xsl:copy>
            <xsl:apply-templates/>
         </xsl:copy>
      </Batch>
   </xsl:template>

   <xsl:template match="Member">
      <xsl:copy>
         <xsl:copy-of select="FirstName"/>
         <ExtraInfo>
            <xsl:apply-templates />
         </ExtraInfo>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="FirstName" />

   <xsl:template match="Books|Stationery">
      <Category>
         <Name>
            <xsl:value-of select="local-name()"/>
         </Name>
         <xsl:apply-templates select="*" mode="Attributes"/>
      </Category>
   </xsl:template>

   <xsl:template match="*" mode="Attributes">
      <attribute>
         <Name>
            <xsl:value-of select="local-name()"/>
         </Name>
         <Value>
            <xsl:choose>
               <xsl:when test=". = 1">True</xsl:when>
               <xsl:otherwise>False</xsl:otherwise>
            </xsl:choose>
         </Value>
      </attribute>
   </xsl:template>
</xsl:stylesheet>

当应用于您的样本输入XML时,输出以下内容:

<Batch>
   <Version>1.0</Version>
   <BatchMember>
      <Member>
         <FirstName>MICHAEL </FirstName>
         <ExtraInfo>
            <Category>
               <Name>Books</Name>
               <attribute>
                  <Name>Fiction</Name>
                  <Value>True</Value>
               </attribute>
               <attribute>
                  <Name>ChildrensBooks</Name>
                  <Value>False</Value>
               </attribute>
            </Category>
            <Category>
               <Name>Stationery</Name>
               <attribute>
                  <Name>Art</Name>
                  <Value>False</Value>
               </attribute>
               <attribute>
                  <Name>Writing</Name>
                  <Value>False</Value>
               </attribute>
            </Category>
            <CardsGifts>1</CardsGifts>
            <ROINI>1</ROINI>
            <Signed>1</Signed>
            <Date>2011-10-04</Date>
         </ExtraInfo>
      </Member>
      <Member>
         <FirstName>JOHN </FirstName>
         <ExtraInfo>
            <Category>
               <Name>Books</Name>
               <attribute>
                  <Name>Fiction</Name>
                  <Value>True</Value>
               </attribute>
               <attribute>
                  <Name>ChildrensBooks</Name>
                  <Value>False</Value>
               </attribute>
            </Category>
            <Category>
               <Name>Stationery</Name>
               <attribute>
                  <Name>Art</Name>
                  <Value>True</Value>
               </attribute>
               <attribute>
                  <Name>Writing</Name>
                  <Value>False</Value>
               </attribute>
            </Category>
            <CardsGifts>1</CardsGifts>
            <ROINI/>
            <Signed>1</Signed>
            <Date>2011-10-04</Date>
         </ExtraInfo>
      </Member>
   </BatchMember>
</Batch>

虽然它与您的预期输出不完全匹配(例如,它仍会输出 CardsGifts 元素),但我希望它可以为您提供一些工作。