首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >xslt group by - php

xslt group by - php
EN

Stack Overflow用户
提问于 2012-02-17 10:14:41
回答 4查看 188关注 0票数 0

嘿,我有一个愚蠢的xml文件:

代码语言:javascript
复制
<?xml version="1.0"?>
 <accidents>
 <accident>
  <org>1</org>
  <com>194</com>
  <dep>010</dep>
  <grav>0.64</grav>
 </accident>
 <accident>
  <org>1</org>
  <com>194</com>
  <dep>420</dep>
  <grav>0.54</grav>
 </accident>
 <accident>
  <org>1</org>
  <com>44</com>
  <dep>010</dep>
  <grav>0.4</grav>
 </accident>
</accidents>

我想要应用xslt 1.0来获得dep的事故数量:输出应该是这样的:

环保部010 :2起事故;环保部420 :1起事故

谢谢,请注意,我使用php,所以不能使用saxon

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-02-17 11:50:51

此转换

代码语言:javascript
复制
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kAccByDept" match="accident" use="dep"/>

 <xsl:template match=
  "accident
    [generate-id()
    =
     generate-id(key('kAccByDept', dep)[1])
     ]">
     <xsl:if test="position() > 1"> ; </xsl:if>

     <xsl:value-of select=
      "concat('dep ', dep, ' : ',
              count(key('kAccByDept', dep)), ' accidents')
      "/>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

在所提供的XML文档上应用时的

代码语言:javascript
复制
<accidents>
    <accident>
        <org>1</org>
        <com>194</com>
        <dep>010</dep>
        <grav>0.64</grav>
    </accident>
    <accident>
        <org>1</org>
        <com>194</com>
        <dep>420</dep>
        <grav>0.54</grav>
    </accident>
    <accident>
        <org>1</org>
        <com>44</com>
        <dep>010</dep>
        <grav>0.4</grav>
    </accident>
</accidents>

生成所需的、正确的结果

代码语言:javascript
复制
dep 010 : 2 accidents ; dep 420 : 1 accidents

说明

  1. .
  2. .

XSLT :OP没有一个真正的处理器--他的工具没有实现xsl:key

在这种情况下,下面的解决方案(注意--这比Muenchian分组的效率低得多)仍然解决了这个问题,并且生成了所需的输出

代码语言:javascript
复制
<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>

     <xsl:template match=
      "accident
        [not(dep
            =
             preceding-sibling::*/dep
             )
        ]
      ">
         <xsl:value-of select=
          "concat('dep ', dep, ' : ',
                  count(following-sibling::*[dep = current()/dep]) +1,
                  ' accidents')
          "/>

         <xsl:if test=
         "following-sibling::*/dep
              [not(. = current()/dep)
              and
               not(.
            =
             ../preceding-sibling::*/dep)
              ]"> ; </xsl:if>
     </xsl:template>
     <xsl:template match="text()"/>
</xsl:stylesheet>

当在相同的文档(上面)上应用时,将产生相同的所需的正确结果:

代码语言:javascript
复制
dep 010 : 2 accidents ; dep 420 : 1 accidents
票数 0
EN

Stack Overflow用户

发布于 2012-02-17 10:57:06

不知道为什么要使用XSLT,但如果必须这样做,您可以更容易地从PHP值创建dom元素:

代码语言:javascript
复制
$dom = new DOMDocument;
$dom->loadXML(file_get_contents('accidents.xml'));
$xpath = new DOMXPath($dom);
$deps = array();
foreach ($xpath->query('/accidents/accident/dep') as $node) {
   $n = $node->nodeValue;
   if (!isset($deps[$n])) {
      $deps[$n] = 0;
   }
   $deps[$n]++;
}

这给出了一个以"dep“为键、以事故号为值的数组。

票数 0
EN

Stack Overflow用户

发布于 2012-02-17 11:29:56

使用:

代码语言:javascript
复制
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:key name="k" match="accident" use="dep"/>

  <xsl:template match="/accidents">
    <xsl:apply-templates select="accident[generate-id() = generate-id(key('k', dep))]"/>
  </xsl:template>

  <xsl:template match="accident">
    <xsl:value-of select="concat('dep ', dep, ' : ', count(key('k', dep)), ' accidents; ')"/>
  </xsl:template>
</xsl:stylesheet>

不使用Muenchian方法的解决方案:

代码语言:javascript
复制
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>

  <xsl:template match="/accidents">
    <xsl:apply-templates select="accident[not(preceding-sibling::accident/dep = dep)]"/>
  </xsl:template>

  <xsl:template match="accident">
    <xsl:value-of select="concat('dep ', dep, ' : ', count(../accident[dep = current()/dep]), ' accidents; ')"/>
  </xsl:template>
</xsl:stylesheet>

输出:

代码语言:javascript
复制
dep 010 : 2 accidents; dep 420 : 1 accidents;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9322008

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档