XSLT Удаление дубликатов - PullRequest
4 голосов
/ 01 апреля 2011

У меня есть источник данных xml, который выглядит следующим образом:

<dsQueryResponse>
  <Department>
    <Rows>
      <Row dept="HR" state="NY" region="East"/>
      <Row dept="HR" state="NJ" region="East"/>
      <Row dept="SD" state="NY" region="East"/>
      <Row dept="MM" state="NY" region="East"/>
      <Row dept="SD" state="NJ" region="East"/>
      <Row dept="SD" state="CO" region="West"/>
      <Row dept="MM" state="CO" region="West"/>
    </Rows>
  </Department>
</dsQueryResponse>

Мой XSLT выглядит так:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:output method="html" indent="no"/>
  <xsl:decimal-format NaN=""/>
  <xsl:param name="DeptQS">East</xsl:param>
  <xsl:variable name="deptRows" select="/dsQueryResponse/Department/Rows/Row[@region = $DeptQS]"/>

  <xsl:template match="/">
    <xsl:if test="count($deptRows) &gt; 0">
      <xsl:call-template name="deptList"/>
    </xsl:if>
  </xsl:template>

  <xsl:template name="deptList">
    <xsl:for-each select="$deptRows">
      <!-- process unique depts--> 
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

Я хочу выписать все департаменты в регионе.Код, который я имею сейчас, выпишет дубликаты отделов.Но как я могу выписать отдел по региону только один раз?

Спасибо!

Ответы [ 4 ]

4 голосов
/ 01 апреля 2011

Вы не показали желаемый результат.Но в XSLT 2.0 вы могли бы сделать что-то вроде этого:

<xsl:template match="Rows">
  <xsl:for-each-group select="Row" group-by="@region">
    <region name="{current-grouping-key()}">
      <xsl:for-each-group select="current-group()" group-by="@dept">
        <dept name="{current-grouping-key()}">
          <xsl:for-each select="current-group()">
            <state name="{@state}"/>
          </xsl:for-each>
        </dept>
      </xsl:for-each-group>
    </region>
  </xsl:for-each>
</xsl:template>
2 голосов
/ 01 апреля 2011

как я могу выписать отдел для регион только один раз?

Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="pRegion" select="'East'"/>
    <xsl:key name="kRowByDept-Region" match="Row"
             use="concat(@dept,'++',@region)"/>
    <xsl:template match="Rows">
        <xsl:apply-templates select="Row[generate-id()
                                          = generate-id(
                                               key('kRowByDept-Region',
                                                   concat(@dept,'++',$pRegion)
                                               )[1]
                                            )
                                     ]"/>
    </xsl:template>
    <xsl:template match="Row">
        <xsl:value-of select="concat(@dept,'&#xA;')"/>
    </xsl:template>
</xsl:stylesheet>

Выход:

HR
SD
MM
2 голосов
/ 01 апреля 2011

Для XSLT 1.0 вы можете использовать " Muenchian Method ".

Вы бы создали ключ для индексации элементов Row по комбинации значений @region и @dept.

Тогда вы получите первое вхождение этой комбинации регион / отдел (в котором есть требуемый регион ($DeptQS)) и выведите отдел (dept).

Вот примертаблица стилей, выводящая <test> элементов для отображения контекста:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="kDept" match="Department/Rows/Row" use="concat(@region,'|',@dept)"/>
  <xsl:param name="DeptQS">East</xsl:param>

  <xsl:template match="/*">
    <xsl:for-each select="Department/Rows/Row[count(.|key('kDept',
      concat($DeptQS,'|',@dept))[1])=1]">
      <test>Current dept: <xsl:value-of select="@dept"/></test>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

Вот вывод с использованием введенного вами XML:

<test>Current dept: HR</test>
<test>Current dept: SD</test>
<test>Current dept: MM</test>
1 голос
/ 01 апреля 2011

Следующая таблица стилей показывает общий подход к группированию на нескольких уровнях:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="byRegion" match="Row" use="@region" />
    <xsl:key name="byRegionState" 
             match="Row" use="concat(@region, '|', @state)" />
    <xsl:key name="byRegionStateDept" 
             match="Row" use="concat(@region, '|', @state, '|', @dept)" />
    <xsl:template 
         match="Row[generate-id() = generate-id(key('byRegion', @region)[1])]">
        <region name="{@region}">
            <xsl:apply-templates
                select="key('byRegion', @region)
                         [generate-id() =
                          generate-id(key('byRegionState',
                                      concat(@region, '|', @state))[1])]"
                mode="states" />
        </region>
    </xsl:template>
    <xsl:template match="Row" mode="states">
        <state name="{@state}">
            <xsl:apply-templates
                select="key('byRegionState', concat(@region, '|', @state))
                         [generate-id() =
                          generate-id(key('byRegionStateDept',
                                concat(@region, '|', @state, '|', @dept))[1])]"
                mode="dept" />
        </state>
    </xsl:template>
    <xsl:template match="Row" mode="dept">
        <dept><xsl:value-of select="@dept" /></dept>
    </xsl:template>
</xsl:stylesheet>

Он выдаст следующий вывод на ваш вход:

<region name="East">
    <state name="NY">
        <dept>HR</dept>
        <dept>SD</dept>
        <dept>MM</dept>
    </state>
    <state name="NJ">
        <dept>HR</dept>
        <dept>SD</dept>
    </state>
</region>
<region name="West">
    <state name="CO">
        <dept>SD</dept>
        <dept>MM</dept>
    </state>
</region>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...