Заключите одноуровневые узлы после данного узла - PullRequest
1 голос
/ 25 октября 2011

Мне нужна помощь во вложении некоторых родственных узлов после узла FirstName в узел ExtraInfo в следующем xml:

<?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 голосов
/ 26 октября 2011

Я думаю, что ваш XSLT может быть слишком сложным. Например, вам не обязательно нужен xsl: key .

То, что вы можете сделать, - это когда вы сопоставляете элемент Member , добавляете специальное кодирование для элемента 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%, что вы хотели с этим сделать, но в вашем ожидаемом результате выглядело, как будто вы хотели преобразовать их в attribute elements.

Вот 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 элементов), я надеюсь, что он может дать вам над чем поработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...