2011-04-01 147 views
4

我有一个XML数据源,看起来像这样:XSLT删除重复

<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> 

我想在写出该地区的所有部门。我现在的代码将写出重复的部门。但是,我怎样才能把该地区的部门只写一次呢?

谢谢!

+0

请提供实际的和预期的结果。否则,很难明确你需要什么。 – oberlies 2014-05-07 15:23:47

回答

2

对于XSLT 1.0,你可以使用 “Muenchian Method”。

您将创建一个密钥来索引元素的组合@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> 
+0

变量/参数引用无效在XSLT 1.0模式**像'的xsl:在XSLT 1.0模式键/ @ match' ** – 2011-04-01 15:52:07

+1

不能使用VAR /参数参考,但你可以在XSLT 2.0。这改变了整个问题,因为在XSLT 1.0中你必须使用推式。你的答案在模式中使用拉式和参数引用。 **这是不是一个XSLT 1.0解决方案,您的第一句话似乎要求。** – 2011-04-01 17:51:24

4

您还没有表现出所需的输出。但在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> 
+0

代码的下半年似乎语法非法的? – 2011-04-01 12:47:30

+1

感谢编辑它,西蒙。我使用' 2013-05-23 06:46:25

2

我怎么能写出来供 该地区只有一次部门?

该样式表:

<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 
1

以下样式示出了一般的方法来在多个级别分组:

<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>