2012-04-26 1 views
1

Учитывая следующий XMLкак выбрать предшествующие узлы в пределах конкретного родителя

<Root> 
<Employee> 
    <service> 
    <Record>xxx</Record> 
    <Record>yyy</Record> 
    </service> 
    <service> 
    <Record>xxx</Record> 
    <Record>yyy</Record> 
    <Record>zzz</Record> 
    </service> 
</Employee> 
<Employee> 
    <service> 
    <Record>xxx</Record> 
    <Record>yyy</Record> 
    </service> 
    <service> 
    <Record>xxx</Record> 
    <Record>yyy</Record> 
    <Record>zzz</Record> 
    </service> 
</Employee> 
</Root> 

Использование XSLT1.0, в то время как преобразование XML для каждого <Employee> в <Record> поле, содержащее «ххх», «YYY», «ZZZ» должен происходить только один раз в результате

<Root> 
<Employee> 
    <Service> 
    <Record>xxx</Record> 
    <Record>yyy</Record> 
    <Record>zzz</Record> 
    </Service> 
</Employee> 
<Employee> 
    <Service> 
    <Record>xxx</Record> 
    <Record>yyy</Record> 
    <Record>zzz</Record> 
<Service> 
</Employee> 
</Root> 

в обмен на каждую петлю Сотрудник I уставшего использование <xsl:if test='not(preceding::./service/Record=$record)'>. Тест отлично работает для первого <Employee>, принимая <Record> для 'xxx', 'yyy', 'zzz' только один раз. Когда итерация переходит к следующему <Employee>, условие проверки также проверяет значения <Record> в первом <Employee>, и оно находит предшествующие узлы, уже существующие со значениями «xxx »,« yyy »,« zzz », поэтому я не могу получить записи для второго <Employee>. Как получить <Record> s во втором <Employee>. Буду признателен за любую оказанную помощь.

Благодаря

ответ

0

Это преобразование использует Muenchian метод для группировки:

<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="kEmpRecordByVal" match="Employee/service/Record" 
    use="concat(generate-id(../..), '+', .)"/> 

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

<xsl:template match="Employee"> 
    <Employee> 
    <xsl:apply-templates select= 
    "service/Record 
      [generate-id() 
      = 
      generate-id(key('kEmpRecordByVal', 
          concat(generate-id(../..), '+', .) 
          )[1] 
         ) 
      ] 
    "/> 
    </Employee> 
</xsl:template> 
</xsl:stylesheet> 

при нанесении на следующем документе XML (предоставленной одной с различными значениями для второго Employee, чтобы помочь читаемости):

Производится требуемый, правильный результат:

<Root> 
    <Employee> 
     <Record>xxx</Record> 
     <Record>yyy</Record> 
     <Record>zzz</Record> 
    </Employee> 
    <Employee> 
     <Record>aaa</Record> 
     <Record>bbb</Record> 
     <Record>ccc</Record> 
    </Employee> 
</Root>