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
xslt在多个嵌套级别按名称对类似项进行分组_Xslt - Fatal编程技术网

xslt在多个嵌套级别按名称对类似项进行分组

xslt在多个嵌套级别按名称对类似项进行分组,xslt,Xslt,我正在尝试使用xslt进行分组优化。优化应该将具有相同名称的项收集到单个items元素中。当所有项都在同一级别时,我可以使用它,但是一些输入将它们嵌套在任意级别,我不知道在这些情况下如何使分组工作 下面是一个工作示例: <process> <op> <group> <op> <item> <name>a</name>

我正在尝试使用xslt进行分组优化。优化应该将具有相同名称的项收集到单个items元素中。当所有项都在同一级别时,我可以使用它,但是一些输入将它们嵌套在任意级别,我不知道在这些情况下如何使分组工作

下面是一个工作示例:

<process>
<op>
    <group>
        <op>
            <item>
                <name>a</name>
                <detail><value>1</value></detail>
            </item>
        </op>
        <op>
            <item>
                <name>a</name>
                <detail><value>2</value></detail>
            </item>
        </op>
        <op>
            <item>
                <name>c</name>
                <name>x1</name>
                <detail><value>3</value></detail>
            </item>
        </op>
    </group>
</op>

A.
1.
A.
2.
C
x1
3.

下面是我的示例转换定义:

<xs:template match="group[op[item[detail]]]">
    <xs:copy>
        <xs:for-each-group select="op" group-by="item/name">
            <op><item>
            <xs:copy-of select="item/name"/>
            <xs:choose>
            <xs:when test="count(current-group()) &gt; 1">
            <details>
            <xs:for-each select="current-group()">
                <detail><value>
                <xs:value-of select="item/detail/value"/>
                </value></detail>
            </xs:for-each>
            </details>
            </xs:when>
            <xs:otherwise>
                <detail><value>
                <xs:value-of select="item/detail/value"/>
                </value></detail>
            </xs:otherwise>
            </xs:choose>
            </item></op>
        </xs:for-each-group>
    </xs:copy>
</xs:template>

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

将“a”项正确分组在一起,将“c”项分开。 但是,如果“a”项被进一步嵌套,它们将从结果中删除:

<process>
<op>
    <group>
        <op>
            <group>
                <op>
                    <item>
                        <name>a</name>
                        <detail><value>1</value></detail>
                    </item>
                </op>
                <op>
                    <item>
                        <name>a</name>
                        <detail><value>2</value></detail>
                    </item>
                </op>
            </group>
        </op>
        <op>
            <item>
                <name>c</name>
                <name>x1</name>
                <detail><value>3</value></detail>
            </item>
        </op>
    </group>
</op>

A.
1.
A.
2.
C
x1
3.

所需的结果XML是:

<process>
<op>
    <group>
        <op>
            <group>
                <op>
                    <item>
                        <name>a</name>
                        <details>
                            <detail><value>1</value></detail>
                            <detail><value>2</value></detail>
                        </details>
                    </item>
                </op>
            </group>
        </op>
        <op>
            <item>
                <name>c</name>
                <name>x1</name>
                <detail><value>3</value></detail>
            </item>
        </op>
    </group>
</op></process>

A.
1.
2.
C
x1
3.

(如果存在多个带有“c”和“x1”的条目,也可以对它们进行分组,但这不是一项要求)

您需要对所有元素进行分组,并确保递归处理那些没有键的元素,下面是一种尝试:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">

<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>

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

<xsl:template match="group[op[item[detail]]]">
    <xsl:copy>
        <xsl:for-each-group select="*" group-by="string(item/name)">
          <xsl:choose>
            <xsl:when test="current-grouping-key() eq ''">
              <xsl:apply-templates select="current-group()"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:copy>
                <item>
                  <xsl:copy-of select="item/name"/>
                  <xsl:choose>
                    <xsl:when test="current-group()[2]">
                      <details>
                        <xsl:copy-of select="current-group()/item/detail"/>
                      </details>
                    </xsl:when>
                    <xsl:otherwise>
                       <xsl:copy-of select="item/detail"/>
                    </xsl:otherwise>
                  </xsl:choose>
                </item>
              </xsl:copy>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each-group>
   </xsl:copy>
</xsl:template>

</xsl:stylesheet>

您需要显示并解释您想要的最后一个输入样本的结果,我不清楚。添加了所需的结果XML,因此您希望保留层次结构,并基本上对每个
组中的
op
元素进行分组。如果有一些
op
元素带有
c
,然后是嵌套组,然后是一些
op
元素带有
,会发生什么情况?你想把所有的
c
项目组合在一起,基本上把后面的元素拉起来吗?或者,如果原始XML中的
op
元素相邻,您是否只想使用相同的
item
对它们进行分组?只需要在原始XML中相邻。这适用于我的所有测试用例,但某些项具有多个name元素的情况除外(抱歉,我没有包括示例)。当存在多个名称时,它在string()调用中出错。只有在所有名称都匹配的情况下,它才应该组合这些项目。您是否可以编辑问题,并用多个名称显示示例和相应的结果?这些名字是排序的还是可排序的?我正在考虑使用例如
groupby=“string join(item/name,“|”)”
,只有对名称进行排序,或者至少可以对名称进行排序,以获得一种指纹来对祖先进行分组。
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs mf">

<xsl:param name="separator" as="xs:string" select="'|'"/>

<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>

<xsl:function name="mf:sort" as="xs:string*">
  <xsl:param name="input"/>
  <xsl:perform-sort select="$input">
    <xsl:sort select="."/>
  </xsl:perform-sort>
</xsl:function>

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

<xsl:template match="group[op[item[detail]]]">
    <xsl:copy>
        <xsl:for-each-group select="*" group-by="string-join(mf:sort(item/name), $separator)">
          <xsl:choose>
            <xsl:when test="current-grouping-key() eq ''">
              <xsl:apply-templates select="current-group()"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:copy>
                <item>
                  <xsl:copy-of select="item/name"/>
                  <xsl:choose>
                    <xsl:when test="current-group()[2]">
                      <details>
                        <xsl:copy-of select="current-group()/item/detail"/>
                      </details>
                    </xsl:when>
                    <xsl:otherwise>
                       <xsl:copy-of select="item/detail"/>
                    </xsl:otherwise>
                  </xsl:choose>
                </item>
              </xsl:copy>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:for-each-group>
   </xsl:copy>
</xsl:template>

</xsl:stylesheet>