Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
返回XML的不同记录_Xml_Xslt - Fatal编程技术网

返回XML的不同记录

返回XML的不同记录,xml,xslt,Xml,Xslt,我对XML和XLST完全陌生。我有一份用XML表示的报告。它有几千条记录,但同样的两行数据被反复重复。我需要一种方法将输出XML文件限制为只有这两行数据 下面是我的XML文件当前外观的示例: <zd:Report_Data xmlns:zd="urn:com.xxxx.report/xxxx-Employee_Status-Outbound"> <zd:Report_Entry> <zd:empStat.emplStatusCode>A</zd:e

我对XML和XLST完全陌生。我有一份用XML表示的报告。它有几千条记录,但同样的两行数据被反复重复。我需要一种方法将输出XML文件限制为只有这两行数据

下面是我的XML文件当前外观的示例:

<zd:Report_Data xmlns:zd="urn:com.xxxx.report/xxxx-Employee_Status-Outbound">
   <zd:Report_Entry>
<zd:empStat.emplStatusCode>A</zd:empStat.emplStatusCode>
<zd:empStat.name>Active Employee</zd:empStat.name>
<zd:worker>
<zd:empStat.lastUpdateDate>1/1/1968</zd:empStat.lastUpdateDate>
<zd:empStat.actvInd>1</zd:empStat.actvInd>
</zd:worker>
   </zd:Report_Entry>
   <zd:Report_Entry>
<zd:empStat.emplStatusCode>A</zd:empStat.emplStatusCode>
<zd:empStat.name>Active Employee</zd:empStat.name>
<zd:worker>
<zd:empStat.lastUpdateDate>1/1/1968</zd:empStat.lastUpdateDate>
<zd:empStat.actvInd>1</zd:empStat.actvInd>
</zd:worker>
   </zd:Report_Entry>
   <zd:Report_Entry>
<zd:empStat.emplStatusCode>A</zd:empStat.emplStatusCode>
<zd:empStat.name>Active Employee</zd:empStat.name>
<zd:worker>
<zd:empStat.lastUpdateDate>1/1/1968</zd:empStat.lastUpdateDate>
<zd:empStat.actvInd>0</zd:empStat.actvInd>
</zd:worker>
   </zd:Report_Entry>
   <zd:Report_Entry>
<zd:empStat.emplStatusCode>A</zd:empStat.emplStatusCode>
<zd:empStat.name>Active Employee</zd:empStat.name>
<zd:worker>
<zd:empStat.lastUpdateDate>1/1/1968</zd:empStat.lastUpdateDate>
<zd:empStat.actvInd>0</zd:empStat.actvInd>
</zd:worker>
   </zd:Report_Entry>
   </zd:Report_Data>

A.
在职员工
1/1/1968
1.
A.
在职员工
1/1/1968
1.
A.
在职员工
1/1/1968
0
A.
在职员工
1/1/1968
0
这就是我希望它看起来的样子:

<zd:Report_Data xmlns:zd="urn:com.xxxx.report/xxxx-Employee_Status-Outbound">
   <zd:Report_Entry>
<zd:empStat.emplStatusCode>A</zd:empStat.emplStatusCode>
<zd:empStat.name>Active Employee</zd:empStat.name>
<zd:worker>
<zd:empStat.lastUpdateDate>1/1/1968</zd:empStat.lastUpdateDate>
<zd:empStat.actvInd>1</zd:empStat.actvInd>
</zd:worker>
   </zd:Report_Entry>
   <zd:Report_Entry>
<zd:empStat.emplStatusCode>A</zd:empStat.emplStatusCode>
<zd:empStat.name>Active Employee</zd:empStat.name>
<zd:worker>
<zd:empStat.lastUpdateDate>1/1/1968</zd:empStat.lastUpdateDate>
<zd:empStat.actvInd>0</zd:empStat.actvInd>
</zd:worker>
   </zd:Report_Entry>
   </zd:Report_Data>

A.
在职员工
1/1/1968
1.
A.
在职员工
1/1/1968
0
^^更新


我在这个网站上看到了一些我认为有用的东西(http://stackoverflow.com/questions/3016929/selecting-unique-records-in-xslt-xpath)但我很难把它应用到我的情况。任何帮助都将不胜感激

这是我到目前为止根据我在这里读到的另一篇文章得出的结论。不幸的是,它没有返回任何数据:

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

    <xsl:key name="kItemBy3Children" match="Report_Entry"
     use="concat(empStat.emplStatusCode, '+', empStat.name, '+', empStat.lastUpdateDate, '+', empStat.actvInd)"/>

 <xsl:template match="/">
       <xsl:copy-of select=
        "*/item[generate-id()
              = generate-id(key('kItemBy4Children',
                                concat(empStat.emplStatusCode,
                                       '+', empStat.name,
                       '+', empStat.lastUpdateDate,     
                                       '+', empStat.actvInd)
                               )
                            )
               ]
        "/>
 </xsl:template>
</xsl:stylesheet>

如果只需要选择前两行,这非常简单:

<xsl:template match="/*">
  <xsl:copy>
    <xsl:copy-of select="*[1]|*[2]"/>
  </xsl:copy>
</xsl:template>


但也许我误解了这个问题。

这是一个不同于您尝试的解决方案,因为我没有使用任何键。我认为这样比较容易,因为您不必知道XSLT中的键是如何工作的(事实上,我不知道它们是如何工作的,因为到目前为止我从未需要它们)

注意,我已经为您的名称空间前缀
ZD
声明了一些URI;您需要插入您的

首先,我应用了身份模板,基本上复制了所有内容

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ZD="http://xyz.abc">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

    <xsl:template match="/ZD:Report_Data/ZD:Report_Entry">
        <xsl:choose>
            <xsl:when test="preceding-sibling::ZD:Report_Entry[(ZD:empStat.emplStatusCode = current()/ZD:empStat.emplStatusCode) and (ZD:empStat.name = current()/ZD:empStat.name) and (ZD:worker/ZD:empStat.lastUpdateDate = current()/ZD:worker/ZD:empStat.lastUpdateDate) and (ZD:worker/ZD:empStat.actvInd = current()/ZD:worker/ZD:empStat.actvInd)]"/>
            <xsl:otherwise>
                <xsl:copy-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
然后,有一个
元素的模板。在该模板中,如果所选元素的前一个同级元素具有相同的内容,则会忽略该元素

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ZD="http://xyz.abc">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

    <xsl:template match="/ZD:Report_Data/ZD:Report_Entry">
        <xsl:choose>
            <xsl:when test="preceding-sibling::ZD:Report_Entry[(ZD:empStat.emplStatusCode = current()/ZD:empStat.emplStatusCode) and (ZD:empStat.name = current()/ZD:empStat.name) and (ZD:worker/ZD:empStat.lastUpdateDate = current()/ZD:worker/ZD:empStat.lastUpdateDate) and (ZD:worker/ZD:empStat.actvInd = current()/ZD:worker/ZD:empStat.actvInd)]"/>
            <xsl:otherwise>
                <xsl:copy-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
转换为此输出:

<ZD:Report_Data xmlns:ZD="http://xyz.abc">
    <ZD:Report_Entry>
        <ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
        <ZD:empStat.name>Active Employee</ZD:empStat.name>
        <ZD:worker>
            <ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
            <ZD:empStat.actvInd>1</ZD:empStat.actvInd>
        </ZD:worker>
    </ZD:Report_Entry>
    <ZD:Report_Entry>
        <ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
        <ZD:empStat.name>Terminated Employee</ZD:empStat.name>
        <ZD:worker>
            <ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
            <ZD:empStat.actvInd>0</ZD:empStat.actvInd>
        </ZD:worker>
    </ZD:Report_Entry>
    <ZD:Report_Entry>
        <ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
        <ZD:empStat.name>Active Employee</ZD:empStat.name>
        <ZD:worker>
            <ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
            <ZD:empStat.actvInd>2</ZD:empStat.actvInd>
        </ZD:worker>
    </ZD:Report_Entry>
</ZD:Report_Data>

A.
在职员工
1/1/1968
1.
A.
终止雇佣
1/1/1968
0
A.
在职员工
1/1/1968
2.

更新:正确地复制了
元素,而不仅仅是它的内容。

我尝试将一些东西放在一起,以便在一般情况下实现您想要的功能,而不是专门针对此XML模式

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ZD="http://xyz.abc">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

    <xsl:template match="/ZD:Report_Data/ZD:Report_Entry">
        <xsl:choose>
            <xsl:when test="preceding-sibling::ZD:Report_Entry[(ZD:empStat.emplStatusCode = current()/ZD:empStat.emplStatusCode) and (ZD:empStat.name = current()/ZD:empStat.name) and (ZD:worker/ZD:empStat.lastUpdateDate = current()/ZD:worker/ZD:empStat.lastUpdateDate) and (ZD:worker/ZD:empStat.actvInd = current()/ZD:worker/ZD:empStat.actvInd)]"/>
            <xsl:otherwise>
                <xsl:copy-of select="."/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>
我很累,这是非常老套和哈奇(注意,在憎恨之前,人们),所以可能有更好的方法,但它似乎工作

    <!-- root and static content -->
    <xsl:template match="/">
        <root>
            <xsl:apply-templates select='*/*' />
        </root>
    </xsl:template>


    <!-- children - output only unique -->
    <xsl:template match='*'>
        <xsl:variable name='node' select='.' />

        <!-- does this node have identical siblings up ahead? If so, skip it, and we'll output a sibling later -->
        <xsl:variable name='has_identical_siblings'>
            <xsl:for-each select='following-sibling::*[name() = name($node)]'>
                <xsl:call-template name='check_identical'>
                    <xsl:with-param name='this_node_profile'>
                        <xsl:copy-of select='$node' />
                    </xsl:with-param>
                    <xsl:with-param name='check_against'>
                        <xsl:copy-of select='.' />
                    </xsl:with-param>
                </xsl:call-template>
            </xsl:for-each>
        </xsl:variable>

        <!-- output? -->
        <xsl:if test='not(normalize-space($has_identical_siblings))'>
            <xsl:copy-of select='.' />
        </xsl:if>
    </xsl:template>

    <!-- util: two nodes are identical? -->
    <xsl:template name='check_identical'>
        <xsl:param name='this_node_profile' />
        <xsl:param name='check_against' />
        <xsl:if test='$this_node_profile = $check_against'>true</xsl:if>
    </xsl:template>

真的
(请参阅输出源-一名在职员工,一名离职)。

此样式表

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:ZD="urn:com.xxxx.report/xxxx-Employee_Status-Outbound">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:key name="kItemBy4Children" match="ZD:Report_Entry"
     use="concat(ZD:empStat.emplStatusCode, '+', ZD:empStat.name, '+', ZD:worker/ZD:empStat.lastUpdateDate, '+', ZD:worker/ZD:empStat.actvInd)"/>

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

 <xsl:template match="ZD:Report_Data">
  <xsl:copy>
    <xsl:apply-templates select="@*" />
    <xsl:copy-of select=
      "ZD:Report_Entry[ generate-id() = generate-id(key('kItemBy4Children',
       concat(ZD:empStat.emplStatusCode, '+', ZD:empStat.name, '+', ZD:worker/ZD:empStat.lastUpdateDate, '+', ZD:worker/ZD:empStat.actvInd))[1])]"/>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

。。。将转换此输入文档

<ZD:Report_Data xmlns:ZD="urn:com.xxxx.report/xxxx-Employee_Status-Outbound">

<ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Active Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>1</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>

<ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Terminated Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>0</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>

<ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Active Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>1</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>

<ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Terminated Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>0</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>

</ZD:Report_Data>
<ZD:Report_Data xmlns:ZD="urn:com.xxxx.report/xxxx-Employee_Status-Outbound">
  <ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Active Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>1</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>
  <ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Terminated Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>0</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>
</ZD:Report_Data>

A.
在职员工
1/1/1968
1.
A.
终止雇佣
1/1/1968
0
A.
在职员工
1/1/1968
1.
A.
终止雇佣
1/1/1968
0
。。。进入此输出文档

<ZD:Report_Data xmlns:ZD="urn:com.xxxx.report/xxxx-Employee_Status-Outbound">

<ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Active Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>1</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>

<ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Terminated Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>0</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>

<ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Active Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>1</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>

<ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Terminated Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>0</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>

</ZD:Report_Data>
<ZD:Report_Data xmlns:ZD="urn:com.xxxx.report/xxxx-Employee_Status-Outbound">
  <ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Active Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>1</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>
  <ZD:Report_Entry>
<ZD:empStat.emplStatusCode>A</ZD:empStat.emplStatusCode>
<ZD:empStat.name>Terminated Employee</ZD:empStat.name>
<ZD:worker>
<ZD:empStat.lastUpdateDate>1/1/1968</ZD:empStat.lastUpdateDate>
<ZD:empStat.actvInd>0</ZD:empStat.actvInd>
</ZD:worker>
</ZD:Report_Entry>
</ZD:Report_Data>

A.
在职员工
1/1/1968
1.
A.
终止雇佣
1/1/1968
0

解释 报表_数据节点按组分组,其内容与4个子成员测量的内容相同。换句话说,每个不同的报表数据只有一个组,并且只输出每个组的第一个成员。这种技术被称为明钦分组。我可以给你一个很长的解释,或者你可以搜索几百个已经解释了这一点的StackOverflow问题。我只会重复别人写的东西

搜索的起点:

  • Stackoverflow(在Muenchian搜索)
  • 谷歌
更新
我对empStat.empostStatusCode字段和empStat.name字段进行了更正,它们的前面应该是ZD:worker/

您已经走了多远?您是否有任何(尚未完全正确的)代码要显示?你到底有什么问题?你对问题的描述越准确,我们就越能向你解释:-)你好,谢谢你的回复。我添加到我的原始帖子是为了向你展示我迄今为止所做的努力。@micheal Kay.不幸的是,这不是我的问题。问题是有数千条记录,但始终是相同的两条,它们不一定是有序的。第一个数据集可能在第二个数据集出现之前显示100倍。@O.R.Mapper…谢谢。让我玩一会儿。我尝试将其转储到xslt中,但没有失败。然而,它也没有过滤掉重复的内容。它返回了报告中的所有数据,而不是我正在查找的2条唯一记录。我肯定这是我的错。我对此完全陌生,所以很难解决我自己的问题。再次感谢您的帮助和耐心。我已经更新了我的答案,因此它包含一个删除重复项的测试用例。我想您可能遇到名称空间不匹配,因此在尝试时只执行了标识模板。是的,您已经执行了。OP需要不同记录的列表。在他的样本数据中,有两个不同的记录,但一般来说,可以有任意数量的记录。他对分组解决问题有正确的总体想法。他只是在将分组应用于他的问题时犯了一些错误。好吧,回答这样的问题可能有点迂腐:“这是相同的两行数据被反复重复。我需要一种方法将输出XML文件限制为仅这两行唯一的数据。”而不是试图解决更一般的问题。谁知道呢?在我看来,这个答案缺乏解释。对于那些还不知道这是如何工作的人来说,这并没有什么帮助