Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.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将2个连续元素合并为1个_Xslt - Fatal编程技术网

使用xslt将2个连续元素合并为1个

使用xslt将2个连续元素合并为1个,xslt,Xslt,我是xslt新手,从几天前开始尝试不同的选项。 我对下面的场景有点不知所措(更多是因为我缺乏xslt方面的知识) 输入xml类似于: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <MAIN> <ProcessResponse> <ORDERNO>workorder123</ORDERNO> <NAME>BD-OC 102

我是xslt新手,从几天前开始尝试不同的选项。 我对下面的场景有点不知所措(更多是因为我缺乏xslt方面的知识)

输入xml类似于:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MAIN>
    <ProcessResponse>
        <ORDERNO>workorder123</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <FID>124</FID>
        <FNO>57</FNO>       
        <AID>126</AID>
        <BID>125</BID>

    </ProcessResponse>
    <ProcessResponse>
        <ORDERNO>workorder123</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <FID>125</FID>
        <FNO>58</FNO>
        <AID>127</AID>
        <BID>128</BID>

    </ProcessResponse>
    <ProcessResponse>
        <ORDERNO>workorder124</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <FID>130</FID>
        <FNO>59</FNO>       
        <AID>132</AID>
        <BID>131</BID>

    </ProcessResponse>
    <ProcessResponse>
        <ORDERNO>workorder124</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <FID>132</FID>
        <FNO>60</FNO>
        <AID>133</AID>
        <BID>134</BID>

    </ProcessResponse>

</MAIN>

工作指令123
BD-OC 102
124
57
126
125
工作指令123
BD-OC 102
125
58
127
128
工作指令124
BD-OC 102
130
59
132
131
工作指令124
BD-OC 102
132
60
133
134
我期望的输出是这样的(基本上我希望每2个连续的元素合并成1个,合并不常见的部分)。 在过程语言中,它应该很简单,但我在xslt中尝试了递归,但并没有得到期望的结果

转换后的输出:

<Response>
    <Process>
        <ORDERNO>workorder123</ORDERNO>
        <NAME>BD-OC 102</NAME>

        <F1>
            <FID>124</FID>
            <FNO>57</FNO>       
            <AID>126</AID>
            <BID>125</BID>
        </F1>

        <F2>
            <FID>125</FID>
            <FNO>58</FNO>
            <AID>127</AID>
            <BID>128</BID>
        </F2>

    </Process>

    <Process>
        <ORDERNO>workorder124</ORDERNO>
        <NAME>BD-OC 102</NAME>
        <F1>
            <FID>130</FID>
            <FNO>59</FNO>       
            <AID>132</AID>
            <BID>131</BID>
        </F1>
        <F2>
            <FID>132</FID>
            <FNO>60</FNO>
            <AID>133</AID>
            <BID>134</BID>
        </F2>

    </Process>


</Response>

工作指令123
BD-OC 102
124
57
126
125
125
58
127
128
工作指令124
BD-OC 102
130
59
132
131
132
60
133
134
注意:实际文件比这复杂得多,但基本思想是一样的,每2个连续块合并为一个(公共部分)


感谢您的帮助/指导/指点。

尝试此基于关键点的解决方案:


将生成以下输出:

<?xml version="1.0"?>
<Response>
  <Process>
    <ORDERNO>workorder123</ORDERNO>
    <NAME>BD-OC 102</NAME>
    <F1>


                <FID>124</FID>
                <FNO>57</FNO>
                <AID>126</AID>
                <BID>125</BID>

        </F1>
    <F2>


                <FID>125</FID>
                <FNO>58</FNO>
                <AID>127</AID>
                <BID>128</BID>

        </F2>
  </Process>
  <Process>
    <ORDERNO>workorder124</ORDERNO>
    <NAME>BD-OC 102</NAME>
    <F1>


                <FID>130</FID>
                <FNO>59</FNO>
                <AID>132</AID>
                <BID>131</BID>

        </F1>
    <F2>


                <FID>132</FID>
                <FNO>60</FNO>
                <AID>133</AID>
                <BID>134</BID>
        </F2>
  </Process>
</Response>

工作指令123
BD-OC 102
124
57
126
125
125
58
127
128
工作指令124
BD-OC 102
130
59
132
131
132
60
133
134
要“合并两个连续的行”,请尝试以下操作:

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

    <xsl:key name="kOrderno" match="ProcessResponse" use="ORDERNO" />
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" >
                <xsl:with-param name="ch" select="h1" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ProcessResponse/ORDERNO"/>
    <xsl:template match="ProcessResponse/NAME"/>
    <xsl:template match="ProcessResponse/text()"/>

    <xsl:template match="/*">
        <Response>
            <xsl:for-each select="ProcessResponse">
                <xsl:if test="position() mod 2 = 1">
                <Process>
                    <xsl:copy-of  select="ORDERNO"/>
                    <xsl:copy-of  select="NAME"/>
                    <xsl:variable name="on" select="ORDERNO" />
                    <xsl:element name="F1">
                        <xsl:apply-templates />
                    </xsl:element>
                    <xsl:element name="F2">
                        <xsl:apply-templates select="following-sibling::ProcessResponse[1]/*" />
                    </xsl:element>
                </Process>
                </xsl:if>
            </xsl:for-each>
        </Response>
    </xsl:template>
</xsl:stylesheet>


哪个xslt版本?合并的规则是什么?是否真的连续,或者更多,因为ORDERNO是相同的?xslt版本1.0规则是:每两个连续(是,因为ORDERNO是相同的)元素(只有2个)将具有相同的ORDERNO。(虽然我想基于orderno做这件事会更通用),但这比我想要的要多(并不是说更多是件坏事)。我非常感激这个答案,我甚至知道xslt有这么多(我生活在java中,顺便说一句,这很深)。但是,您依赖于orderNo来对元素进行分组,我的实际xml要复杂得多,大约有8个公共字段(不共享xml,因为这可能是适当的)。因此,我最好的办法是合并两个连续的行(我正在生成的xml也是从db行中生成的,正如“MUENCHIAN”方法中提到的。有趣的是,我如何解释您的评论:“(虽然我猜基于orderno进行操作会更通用),但这比我想要的要多(不是说更多是坏事)。”按orderno进行分组可能就是您要寻找的。因此orderno对于两个元素来说不是唯一的?是的,我的错,这里的要点是实际xml大约有8个元素,它们的组合是唯一的。我创建了上面的伪xml来模拟类似的条件。我可以认为可行的解决方案是合并两个连续的元素(因为从db到xml的查询总是只返回2条记录,很少有公共记录(orderno、abc、xyz、message等)。很抱歉我的评论模棱两可。我想更新你的答案,但不允许说我需要15次才能做到。你的答案很棒,但目前对我不起作用。非常感谢,它很有魅力。我从你的回答中得到的概念是“position()mod 2=1”和“following sibling”我不知道,你在周末救了我的命。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:key name="kOrderno" match="ProcessResponse" use="ORDERNO" />
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" >
                <xsl:with-param name="ch" select="h1" />
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="ProcessResponse/ORDERNO"/>
    <xsl:template match="ProcessResponse/NAME"/>
    <xsl:template match="ProcessResponse/text()"/>

    <xsl:template match="/*">
        <Response>
            <xsl:for-each select="ProcessResponse">
                <xsl:if test="position() mod 2 = 1">
                <Process>
                    <xsl:copy-of  select="ORDERNO"/>
                    <xsl:copy-of  select="NAME"/>
                    <xsl:variable name="on" select="ORDERNO" />
                    <xsl:element name="F1">
                        <xsl:apply-templates />
                    </xsl:element>
                    <xsl:element name="F2">
                        <xsl:apply-templates select="following-sibling::ProcessResponse[1]/*" />
                    </xsl:element>
                </Process>
                </xsl:if>
            </xsl:for-each>
        </Response>
    </xsl:template>
</xsl:stylesheet>