цикл по узлам, условие отбора которого лежит во внутренних узлах

Alexandre

PHPПенсионер
Организация GROUP BY

может я сказал не так, но мне надо организовать следующий цикл:
есть данные
PHP:
<root order="ascending">
  <project>
    <id>33</id>
...
    <name>Новый проект_1</name>
    <task>
    <name>Task_1</name>
      <work>
         <name>Новая работа1</name>
         <dt>2004-08-25T00:00:00</dt>
         <hours>3</hours>
        </work>
      </task>
      <task>....</task>
   </project>
</root>
Нужно вывести все работы, сгруппированные по дате
т.е. аналог GROUP BY

ну и в добавок еще посчитать сумму часов в каждом блоке работ (за каждый день)
 

Alexandre

PHPПенсионер
НЕТ, chameleon то было - аналог SELECT DISTINCT
а это аналог
SELECT GROUP BY
 

Alexandre

PHPПенсионер
класс!!!, кажется то, что нужно,
попробую

-~{}~ 30.08.04 11:46:

или я тупой, или что-то не так понял?
PHP:
<xsl:tempate name="mytemplate">
<xsl:variable name="unq_date" select="work/dt[generate-id(.) = generate-id( key('k_dt'), work/dt )]"/>
		
nodes=<xsl:value-of select="count($unq_date)"  />

<xsl:for-each  select="$unq_date" >
		<tr bgcolor="#FFFFFF"><td colspan="8"><xsl:value-of select="$unq_date"   />
		</td>
		</tr>		
		<tr bgcolor="#FFFFFF">
</xsl:for-each>  		
<xsl:key name="k_dt" match="root/project/task" use="work/dt"/>
</xsl:tempate >
выдает значение кол-ва узлов nodes=0, хотя данные есть

-~{}~ 30.08.04 11:49:

если я делаю
PHP:
<xsl:variable name="unq_date" select="root/project/task/work/dt[generate-id(.) = generate-id( key('k_dt'), root/project/task/work/dt )]"/>
то выдается ОШИБКА: Неверное число аргументов функции XSLT 'key'.

chameleon что посоветуешь?
 

chameleon

Новичок
для начала посоветую <xsl:key/> вынести из шаблонного правила. Он должен быть дочкой stylesheet'а
 

Alexandre

PHPПенсионер
в твоем примере выше key - дочка template'a что неправильно.
возсожно это опечатка, тк я выносил не весь код а его основу,
если key является дочкой template'a - то выдается ОШИБКА, что дочкой быть не может!!!

-~{}~ 30.08.04 13:27:

chameleon лучше подскажи, почему
Код:
nodes=<xsl:value-of select="count($unq_date)"  />
пустой нодесет
 

chameleon

Новичок
Т.е. декларацию ключа ты перенес и на него больше не ругается? ок.
Тогда дальше по твоему коду судить трудно. Ты даешь кусок именованного шаблона...откуда он вызвается? контекстный узел какой? <task>?
 

Alexandre

PHPПенсионер
chameleon

контекстный узел <root>
у меня все вызывается из рута,
я же писал (предыдущий топик, сам просил рассказать про систему), что анализируется <action> и вызывает тот шаблон, который указан в <action> с помощью <call-template>

контекстный узел в каждом шаблоне <root>

кстати понял почему дата не групируется, у меня дата каждая дата уникальное значение, т.к. там присутствуют сек и мин.
Но после устранения все равно не работает.
 

chameleon

Новичок
Если это
контекстный узел <root>
и это
<xsl:variable name="unq_date" select="work/dt[generate-id(.) = generate-id( key('k_dt'), work/dt )]"/>
так и есть, то конечно будет пустой. Тот xpath, который у тебя в селекте относительно root будет содержать пустой nodeset.
 

Alexandre

PHPПенсионер
Тот xpath, который у тебя в селекте относительно root будет содержать пустой nodeset.
chameleon я это интуитивно понимаю, но вставляю полный путь относительно роот, и у меня все равно NodeSet пустой

<xsl:variable name="unq_date" select="root/project/task/work/dt[generate-id(.) = generate-id( key('k_dt'), root/project/task/work/dt )]"/>
как правильно?

-~{}~ 30.08.04 16:29:

я себе упрощаю задачу, хочу сгруппировать по именам проекта (2й уровень вложенности)
делаю
PHP:
<xsl:variable name="unq_date" select="root/project[generate-id(.) = generate-id( key('k_dt', root/project)  )  ]" />
а 
<xsl:key name="k_dt" match="root" use="project"/>
и все равно нодесет пустой
PHP:
<root order="ascending"> 
  <project> 
    <id>33</id> 
... 
    <name>Новый проект_1</name> 
.....
 

chameleon

Новичок
<xsl:variable name="unq_date" select="root/project/task/work/dt[generate-id(.) = generate-id( key('k_dt'), root/project/task/work/dt )]"/>
эта...у тебя ключ используется для task'ов...какого ты ему суешь dt?
короче :)..
ключ:
PHP:
<xsl:key match="work" name="unq_date" use="date" />
xpath:
PHP:
select="/root/project/task/work[generate-id(.) = generate-id(key('unq_date',date))]"
вроде так.
 

chameleon

Новичок
Это не принципиально в данном случае, match - это те узлы для которых декларирутеся ключ. Можешь написать match="/root/project/task/work" - это более специфический набор только и всего.
 

Alexandre

PHPПенсионер
Решение проблемы

заключается в следующем:
1) организуем ключи
PHP:
 <xsl:key name="k_dt" match="work" use="dt2"/>
Особая заметка, сделал поле dt2 = substring(dt,1,10), т.е
моя дата уникальна, т.к. включает сек и мин...
а мне нужны группировке только по дням!!!!
2)
PHP:
<xsl:variable name="unq_date" select="root/project/task/work[generate-id(.) = generate-id( key('k_dt', dt2 ) )  ]" />

nodes=<xsl:value-of select="count($unq_date)"  /><br/>
Переменная $unq_date содержит узлы с уникальными датами, по которым мне надо осуществить сортировку.
( nodes= показывает кол-во узлов или уникальных дат)
это тестовая переменная для отладки.

3)Организуем обход узлов с вызовом шаблона, который вывадит все данные , содержащие указанную дату.
PHP:
<xsl:for-each  select="$unq_date/dt2" >
	   <xsl:call-template name="group" >
	     <xsl:with-param name="date"><xsl:value-of select="text()"/></xsl:with-param>	     
	   </xsl:call-template>
	   
</xsl:for-each>
4) Сам Шаблон
PHP:
 <xsl:template name="group">
<xsl:param name="date"/>

		<tr bgcolor="#FFFFFF" class="description"><td colspan="8">  <b><xsl:value-of select="$date" /> </b>
		</td>
		</tr>		



	<xsl:for-each select="//work[ substring(dt2,1,10) = substring($date,1,10) ]">
		<tr bgcolor="#FFFFFF">	
			<td class="content" width="18"><img src="images/asp.gif" border="0" align="left"/></td>
			<td class="content" align="left" >

				<xsl:element name="a">
					<xsl:attribute name="href">project.aspx?action=editwork&amp;id=<xsl:value-of select="id" /></xsl:attribute>
					<xsl:attribute name="class">contentlink</xsl:attribute>
					<xsl:value-of select="name" /> 
				</xsl:element>

			</td>

			<td class="content" align="left" >

				<xsl:element name="a">
					<xsl:attribute name="href">project.aspx?action=edit&amp;id=<xsl:value-of select="../proj_id" /></xsl:attribute>
					<xsl:attribute name="class">contentlink</xsl:attribute>
					<xsl:value-of select="../name" /> 
				</xsl:element>
			</td>

			<td class="content" align="left" >
				<xsl:element name="a">
					<xsl:attribute name="href">project.aspx?action=edittask&amp;id=<xsl:value-of select="../../id" /></xsl:attribute>
					<xsl:attribute name="class">contentlink</xsl:attribute>
					<xsl:value-of select="../../name" /> 
				</xsl:element>

			</td>
			
			<td class="content"  align="left" width="12">
					<xsl:value-of select="hours" /> 
			</td>	
			<td class="content"  align="left" width="12">
					<xsl:value-of select="substring(dt,9,2)" />.<xsl:value-of select="substring(dt,6,2)" />.<xsl:value-of select="substring(dt,1,4)" />  
			</td>	
		</tr>
	
	</xsl:for-each>
	 
		<tr bgcolor="#FFFFFF" class="description"><td colspan="4">  <b>Итого:</b></td>
		<td >  <b><xsl:value-of select="sum(//work[ substring(dt2,1,10) = substring($date,1,10)]/hours )" /> </b> </td>
		
		</tr>		
   

</xsl:template>
-~{}~ 31.08.04 11:54:

если предложите другие варианты, то рад буду их применить
 

jian

Guest
xml
Код:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="uniq2.xsl"?>
<root order="ascending"> 
  <project> 
    <id>33</id> 
    <name>new project1</name> 
    <task>
     <name>Task_1</name> 
     <work> 
        <name>new work1</name> 
        <dt>2004-08-25T00:00:00</dt> 
        <hours>3</hours> 
      </work> 
    </task> 
    <task>
     <name>Task_2</name> 
     <work> 
        <name>new work2</name> 
        <dt>2004-08-25T00:00:00</dt> 
        <hours>3</hours> 
      </work> 
    </task> 
    <task>
     <name>Task_3</name> 
     <work> 
        <name>new work3</name> 
        <dt>2004-08-23T00:00:00</dt> 
        <hours>3</hours> 
      </work> 
    </task> 
    <task>
     <name>Task_4</name> 
     <work> 
        <name>new work4</name> 
        <dt>2004-08-25T00:00:00</dt> 
        <hours>3</hours> 
      </work> 
    </task> 

    <task>
     <name>Task_5</name> 
     <work> 
        <name>new work5</name> 
        <dt>2004-08-23T00:00:00</dt> 
        <hours>8</hours> 
      </work> 
    </task> 

  </project> 
</root>
xsl
Код:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output  method = "html" version = "4.0" encoding = "windows-1251" 
media-type = "text/html; charset=windows-1251" 
/> 

<xsl:key name="chislo" match="work" use="substring(dt,1,10)"/>


<xsl:template match="/">
<xsl:apply-templates
select="root/project/task/work[generate-id(.)=generate-id(key('chislo',substring(dt,1,10)))]"/> 
</xsl:template> 

<xsl:template match="work">
[<xsl:value-of select="dt"/>]<br/>
<xsl:apply-templates
select="key('chislo',substring(dt,1,10))" mode="grouped"/> 
__________________________
<xsl:value-of select="sum(key('chislo',substring(dt,1,10))/hours)"/>
<br/>
</xsl:template> 



<xsl:template match="work" mode="grouped">
  <xsl:value-of select="../name"/>/
  <xsl:value-of select="name"/>. 
  <xsl:value-of select="hours"/> hours<br/>
</xsl:template> 

</xsl:stylesheet>
resultat
Код:
[2004-08-25T00:00:00]
Task_1/ new work1. 3 hours
Task_2/ new work2. 3 hours
Task_4/ new work4. 3 hours
__________________________ 9
[2004-08-23T00:00:00]
Task_3/ new work3. 3 hours
Task_5/ new work5. 8 hours
__________________________ 11

cheers
 

chameleon

Новичок
вооот jian не поленился :)... на первый взгляд все красиво.... да вроде и на второй тоже :)...
 
Сверху