2013-08-24 5 views
1

У меня есть документ, как это:XSLT преобразование документа с группой элементов

<?xml version="1.0" encoding="UTF-8"?> 
<document> 
    <data attribute1="12" attribute2="1" attribute3="1">Director</data> 
    <data attribute1="12" attribute2="1" attribute3="5">James</data> 
    <data attribute1="12" attribute2="1" attribute3="8">Male</data> 
    <data attribute1="12" attribute2="1" attribute3="9">10-Dec-1965</data> 
    <data attribute1="12" attribute2="2" attribute3="18">[email protected]</data> 
    <data attribute1="12" attribute2="2" attribute3="1">Chief Account</data> 
    <data attribute1="12" attribute2="2" attribute3="5">Anna</data> 
    <data attribute1="12" attribute2="2" attribute3="8">Female</data> 
    <data attribute1="12" attribute2="1" attribute3="9">5-Aug-1980</data> 
    <data attribute1="12" attribute2="2" attribute3="18">[email protected]</data> 
</document> 

Я хочу, чтобы преобразовать его в этом:

<Person> 
    <Title>Director</Title> 
    <FullName>James</FullName> 
    <Gender>Male</Gender> 
    <DateOfBirth>10-Dec-1965</DateOfBirth> 
    <EmailAddress>[email protected]</EmailAddress> 
</Person> 
<Person> 
    <Title>Chief Account</Title> 
    <FullName>Anna</FullName> 
    <Gender>Female</Gender> 
    <DateOfBirth>5-Aug-1980</DateOfBirth> 
    <EmailAddress>[email protected]</EmailAddress> 
</Person> 

Я использую этот XSLT:

<xsl:for-each select="document/data[@attribute1=12]"> 
    <Person> 
     <xsl:choose> 
      <xsl:when test="boolean(./@attribute3 = '1')"> 
       <Title> 
        <xsl:value-of select="./."/> 
       </Title> 
      </xsl:when> 
      <xsl:when test="boolean(./@attribute3 = '5')"> 
       <FullName> 
        <xsl:value-of select="./."/> 
       </FullName> 
      </xsl:when> 
      <xsl:when test="boolean(./@attribute3 = '8')"> 
       <Gender> 
        <xsl:value-of select="./."/> 
       </Gender> 
      </xsl:when> 
      <xsl:when test="boolean(./@attribute3 = '9')"> 
       <DateOfBirth> 
        <xsl:value-of select="./."/> 
       </DateOfBirth> 
      </xsl:when> 
      <xsl:when test="boolean(./@attribute3 = '18')"> 
       <EmailAddress> 
        <xsl:value-of select="./."/> 
       </EmailAddress> 
      </xsl:when> 
     </xsl:choose> 
    </Person> 
</xsl:for-each> 

Проблема в том, что я получаю следующий вывод, где дублируется тег <Person>.

<Person> 
    <Title>Director</Title> 
</Person>  
<Person>  
    <FullName>James</FullName> 
</Person>  
<Person> 
    <Gender>Male</Gender> 
</Person> 
<Person>  
    <DateOfBirth>10-Dec-1965</DateOfBirth> 
</Person>  
<Person>  
    <EmailAddress>[email protected]</EmailAddress> 
</Person> 
<Person> 
    <Title>Chief Account</Title> 
</Person> 
<Person> 
    <FullName>Anna</FullName> 
</Person> 
<Person> 
    <Gender>Female</Gender> 
</Person> 
<Person> 
    <DateOfBirth>5-Aug-1980</DateOfBirth> 
</Person> 
<Person> 
    <EmailAddress>[email protected]</EmailAddress> 
</Person> 

Может ли кто-нибудь помочь мне решить эту проблему? Спасибо!

+0

Пожалуйста, показывают, что выход. Правильно ли, что у одного из лиц есть два DateOfBirth, а у другого нет, или я не понимаю ваше картографирование? – usr2564301

+0

Можете ли вы использовать XSLT 2.0, так как вы могли бы использовать функцию ** xsl: for-each-group ** здесь. –

+0

@ Jongware: есть два человека, и каждый человек имеет свой собственный DateOfBirth (James-1965 & Anna 1980). Первые пять элементов принадлежат к информации Джеймса, и пять последователей принадлежат к информации Анны. –

ответ

0

Похоже, что вы хотите создать новый Person элемента для каждого данных элемента со значением 1 attribute3. Вместо того, чтобы перебирать все данных элементов, которые вы сейчас делаете, просто выберите элементы с соответствующим атрибутом

<xsl:apply-templates select="data[@attribute3='1']"/> 

Тогда у вас будет шаблон для вывода Лицо элемент только для этих данные элементы.

<xsl:template match="data[@attribute3='1']"> 
    <Person> 
     <Title><xsl:value-of select="." /></Title> 
     <!-- Select other elements here --> 
    </Person> 
</xsl:template> 

Теперь, чтобы получить другие элементы, другой способ достичь этого - использовать ключ. Фактически вы будете группировать данные элементов по первым наиболее предыдущим данные элемент с атрибутом значение «1».

<xsl:key name="data" 
     match="data[@attribute3 != '1']" 
     use="generate-id(preceding-sibling::data[@attribute3 = '1'][1])" /> 

Затем, чтобы выбрать другие элементы, вы можете использовать этот ключ, используя уникальный идентификатор текущего данных элемента в качестве поиска.

<xsl:apply-templates select="key('data', generate-id())" /> 

Это только выбрать данные элементы, которые составляют этот конкретный человек элемент. Вы бы тогда шаблон, чтобы соответствовать другим ДАННЫЕ элементов для каждого возможного значения атрибута:

Try это XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:key name="data" match="data[@attribute3 != '1']" use="generate-id(preceding-sibling::data[@attribute3 = '1'][1])" /> 

    <xsl:template match="document"> 
     <xsl:apply-templates select="data[@attribute3='1']"/> 
    </xsl:template> 

    <xsl:template match="data[@attribute3='1']"> 
     <Person> 
     <Title><xsl:value-of select="." /></Title> 
     <xsl:apply-templates select="key('data', generate-id())" /> 
     </Person> 
    </xsl:template> 

    <xsl:template match="data[@attribute3='5']"> 
     <FullName><xsl:value-of select="." /></FullName> 
    </xsl:template> 

    <xsl:template match="data[@attribute3='8']"> 
     <Gender><xsl:value-of select="." /></Gender> 
    </xsl:template> 

    <xsl:template match="data[@attribute3='9']"> 
     <DateOfBirth><xsl:value-of select="." /></DateOfBirth> 
    </xsl:template> 

    <xsl:template match="data[@attribute3='18']"> 
     <EmailAddress><xsl:value-of select="." /></EmailAddress> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Поблагодарите Тим за указанные указания. Это ответ, который я ожидал –

+0

Помните, что этот ответ основан на позиции элементов, а не в значении ** attribute2 ** в этом случае. –

0

Вот мое предложение, основываясь на положении элементов:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:output method="xml" indent="yes"/> 

<xsl:param name="size" select="5"/> 

<xsl:template match="document"> 
    <Persons> 
    <xsl:apply-templates select="data[position() mod $size = 1]" mode="group"/> 
    </Persons> 
</xsl:template> 

<xsl:template match="data" mode="group"> 
    <Person> 
    <xsl:apply-templates select=". | following-sibling::data[position() &lt; $size]"/> 
    </Person> 
</xsl:template> 

<xsl:template match="data[@attribute3 = '1']"> 
    <Title> 
    <xsl:value-of select="."/> 
    </Title> 
</xsl:template> 

<xsl:template match="data[@attribute3 = '5']"> 
    <FullName> 
    <xsl:value-of select="."/> 
    </FullName> 
</xsl:template> 

<xsl:template match="data[@attribute3 = '8']"> 
    <Gender> 
    <xsl:value-of select="."/> 
    </Gender> 
</xsl:template> 

<xsl:template match="data[@attribute3 = '9']"> 
    <DateOfBirth> 
    <xsl:value-of select="."/> 
    </DateOfBirth> 
</xsl:template> 

<xsl:template match="data[@attribute3 = '18']"> 
    <EmailAddress> 
    <xsl:value-of select="."/> 
    </EmailAddress> 
</xsl:template> 

</xsl:stylesheet> 
+0

Спасибо Мартину. Он работает отлично. Но в случае, если размер не указан, как определить размер базы на атрибут2. Потому что атрибут2 изменяется для каждой информации о группе человека. –

+0

Я не понимаю, почему вы говорите, что 'attribute2' изменяется для каждой группы, так как ваш образец ввода содержит два элемента данных с датами внутри, которые имеют одинаковый атрибут2 (например,' '1" '). Таким образом, по крайней мере, с вашими примерными данными этот атрибут, похоже, не помогает связать элементы с людьми. Если элементы 'data' могут быть сгруппированы по значению' attribute2', тогда может быть применена стандартная группировка Muenchian. Пожалуйста, исправьте данные образца. Или объясните более подробно, как порядок элементов и 'attribute2' связывает элементы данных с людьми. –

Смежные вопросы