XSLT嵌套组

时间:2018-08-07 20:17:55

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

我正在尝试创建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的分组功能所做的

<?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>
            <mheader>
                <mid>1</mid>
                <mname>mn</mname>
            </mheader>
            <cheader>
                <cid>1</cid>
                <cname>cn</cname>
            </cheader>
            </location>

任何人都可以帮助我创建正确的分组层次结构

谢谢。

1 个答案:

答案 0 :(得分:0)

如评论中所述,根据您的需要,可以将两个元素复制到内部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有一个在线示例。