【问题标题】:XSLT Nested GroupsXSLT 嵌套组
【发布时间】:2018-08-07 20:17:54
【问题描述】:

我正在尝试创建一个 XSLT 来转换 XML 文档,但在形成嵌套组时遇到了麻烦。下面是我的 xml

 <?xml version="1.0" encoding="UTF-8"?>
        <catalog>

           <mheader>
              <mid>1</mid>
              <mname>mn</mname>
           </mheader>
           <cheader>
              <cid>1</cid>
              <cname>cn</cname>
           </cheader>
           <lheader>
              <lid>1</lid>
              <lname>ln</lname>
           </lheader>
           <aheader>
              <aid>1</aid>
              <aname>an</aname>
           </aheader>
           <pos>
              <pid>1</pid>
              <pname>pay</pname>
           </pos>
           <pos>
              <pid>2</pid>
              <pname>pay1</pname>
           </pos>

    <lheader>
              <lid>1</lid>
              <lname>ln</lname>
           </lheader>
           <aheader>
              <aid>1</aid>
              <aname>an</aname>
           </aheader>
           <pos>
              <pid>1</pid>
              <pname>pay</pname>
           </pos>
           <pos>
              <pid>2</pid>
              <pname>pay1</pname>
           </pos>

           <mheader>
              <mid>2</mid>
              <mname>mh1</mname>
           </mheader>
           <cheader>
              <cid>2</cid>
              <cname>ch1</cname>
           </cheader>
           <lheader>
              <lid>2</lid>
              <lname>lh1</lname>
           </lheader>
           <aheader>
              <aid>2</aid>
              <aname>ah1</aname>
           </aheader>
           <pos>
              <pid>1</pid>
              <pname>pay</pname>
           </pos>
           <pos>
              <pid>2</pid>
              <pname>pay3</pname>
           </pos>
           <pos>
              <pid>3</pid>
              <pname>pay4</pname>
           </pos>

        </catalog>

我必须像下面那样转换我的 xml

        <?xml version="1.0" encoding="UTF-8"?>
    <catalog>
        <record>
            <mheader>
                <mid>1</mid>
                <mname>mn</mname>
            </mheader>
            <cheader>
                <cid>1</cid>
                <cname>cn</cname>
            </cheader>
            <location>
                <lheader>
                    <lid>1</lid>
                    <lname>ln</lname>
                </lheader>
                <aheader>
                    <aid>1</aid>
                    <aname>an</aname>
                </aheader>
                <pos>
                    <pid>1</pid>
                    <pname>pay</pname>
                </pos>
                <pos>
                    <pid>2</pid>
                    <pname>pay1</pname>
                </pos>
                </location>
                    <location>
                        <lheader>
                            <lid>1</lid>
                            <lname>ln</lname>
                        </lheader>
                        <aheader>
                            <aid>1</aid>
                            <aname>an</aname>
                        </aheader>
                        <pos>
                            <pid>1</pid>
                            <pname>pay</pname>
                        </pos>
                        <pos>
                            <pid>2</pid>
                            <pname>pay1</pname>
                        </pos>
                        </location>
        </record>
        <record>
            <mheader>
                <mid>2</mid>
                <mname>mh1</mname>
            </mheader>
            <cheader>
                <cid>2</cid>
                <cname>ch1</cname>
            </cheader>
<location>
            <lheader>
                <lid>2</lid>
                <lname>lh1</lname>
            </lheader>
            <aheader>
                <aid>2</aid>
                <aname>ah1</aname>
            </aheader>
            <pos>
                <pid>1</pid>
                <pname>pay</pname>
            </pos>
            <pos>
                <pid>2</pid>
                <pname>pay3</pname>
            </pos>
            <pos>
                <pid>3</pid>
                <pname>pay4</pname>
            </pos>
</location>
            <location>
                <lheader>
                    <lid>2</lid>
                    <lname>lh1</lname>
                </lheader>
                <aheader>
                    <aid>2</aid>
                    <aname>ah1</aname>
                </aheader>
                <pos>
                    <pid>1</pid>
                    <pname>pay</pname>
                </pos>
                <pos>
                    <pid>2</pid>
                    <pname>pay3</pname>
                </pos>
                <pos>
                    <pid>3</pid>
                    <pname>pay4</pname>
                </pos>
            </location>
        </record>
    </catalog>

这是我迄今为止使用 XSLT 的 group by 功能所做的

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:preserve-space elements="xsl:text"/>
    <xsl:strip-space elements="*"/>
    <xsl:output encoding="utf-8" method="xml" indent="yes"/>

 <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="catalog">
        <xsl:copy>
            <xsl:for-each-group select="*" group-starting-with="mheader">
                <Record>
                    <xsl:for-each-group select="current-group()" group-starting-with="lheader">
                    <location>
                        <xsl:copy-of select="current-group()"/>
                    </location>
          </xsl:for-each-group>
                </Record>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

但是在转换后的 xml 中,mheader 和 cheader 标记被包裹在 location 标记中,如下所示

<location>
            <mheader>
                <mid>1</mid>
                <mname>mn</mname>
            </mheader>
            <cheader>
                <cid>1</cid>
                <cname>cn</cname>
            </cheader>
            </location>

谁能帮我创建正确的分组层次结构

提前致谢。

【问题讨论】:

  • 你知道mheadercheader这两个元素总是在你想在内部分组中分组的lheader元素之前吗?或者它们也可以出现在和lheader之后,然后需要分组和包装?如果您知道要将 mheadercheader 复制为 Record 的子级,请使用例如&lt;xsl:copy-of select="current-group()[self::mheader | self::cheader]"/&gt; 在嵌套分组之前,您只处理 &lt;xsl:for-each-group select="current-group()[not(self::mheader | self::cheader)]" ...&gt;

标签: xslt xslt-1.0 xslt-2.0 xslt-grouping xslt-3.0


【解决方案1】:

正如评论中所说,根据您的需要,将这两个元素复制到内部 for-each-group 之前的输出中,然后将它们从内部分组中排除就足够了:

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

  <xsl:mode on-no-match="shallow-copy"/>

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

    <xsl:template match="catalog">
        <xsl:copy>
            <xsl:for-each-group select="*" group-starting-with="mheader">
                <Record>
                    <xsl:copy-of select="current-group()[self::mheader | self::cheader]"/>
                    <xsl:for-each-group select="current-group()[not(self::mheader | self::cheader)]" group-starting-with="lheader">
                    <location>
                        <xsl:copy-of select="current-group()"/>
                    </location>
          </xsl:for-each-group>
                </Record>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/eiZQaFv 有一个在线示例。

【讨论】:

  • 感谢这对我帮助很大
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
  • 2015-04-10
  • 1970-01-01
相关资源
最近更新 更多