sequences in XSLT

2020-04-01 03:19发布

问题:

my xml input is-

<?xml version="1.0" encoding="UTF-8"?> 
<foo>  <bar>bar</bar> 
       <bar>bar</bar> 
       <foobar>foobar</foobar> 
       <foobar>foobar</foobar> 
       <foobar>foobar</foobar>
       <bar>bar</bar>
       <bar>bar</bar> 
</foo>

Output using xslt should be

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

 <foo>  
 <s> 
 <s> 
 <bar>bar</bar>  
 <bar>bar</bar>
 </s>
 <s> 
 <foobar>foobar></foobar>
 <foobar>foobar></foobar>
 <foobar>foobar></foobar>
 </s> 
 <s>      
 <bar>bar</bar>  
 <bar>bar</bar> 
 </s>
 </s>
</foo>

the output should to have sequence-of elements inside a parent. Mixed sequence-of elements will be moved inside parents node “s”. Is there any xslt command that detects the sequence and process the xml accordingly.Many thanks.

回答1:

Same as here, use the id of the first preceding sibling whose name is different in order to group the records:

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

<xsl:key name="adjacentByName" match="foo/*" use="generate-id(preceding-sibling::*[not(name()=name(current()))][1])" />

<xsl:template match="/">
<foo><s>
    <xsl:for-each select="foo/*[generate-id()=generate-id(key('adjacentByName', generate-id(preceding-sibling::*[not(name()=name(current()))][1]))[1])]">
        <s>
            <xsl:for-each select="key('adjacentByName', generate-id(preceding-sibling::*[not(name()=name(current()))][1]))">
                <xsl:copy-of select="."/>
            </xsl:for-each>
        </s>
    </xsl:for-each>
</s></foo>
</xsl:template>

</xsl:stylesheet>

Added:

But the output i am getting is not same as my desired output...

When applied to your (cleaned up) input of:

<?xml version="1.0" encoding="UTF-8"?> 
<foo>
    <bar>bar</bar> 
    <bar>bar</bar> 
    <foobar>foobar</foobar> 
    <foobar>foobar</foobar> 
    <foobar>foobar</foobar>
    <bar>bar</bar>
    <bar>bar</bar> 
</foo>

the result is:

<?xml version="1.0" encoding="utf-8"?>
<foo>
  <s>
    <s>
      <bar>bar</bar>
      <bar>bar</bar>
    </s>
    <s>
      <foobar>foobar</foobar>
      <foobar>foobar</foobar>
      <foobar>foobar</foobar>
    </s>
    <s>
      <bar>bar</bar>
      <bar>bar</bar>
    </s>
  </s>
</foo>

which to me seems to be exactly the result you have asked for:

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

 <foo>  
 <s> 
 <s> 
 <bar>bar</bar>  
 <bar>bar</bar>
 </s>
 <s> 
 <foobar>foobar></foobar>
 <foobar>foobar></foobar>
 <foobar>foobar></foobar>
 </s> 
 <s>      
 <bar>bar</bar>  
 <bar>bar</bar> 
 </s>
 </s>
</foo>

except for the > characters inside the <foobar> elements, which I have removed from the input.

--

P.S. Please DO NOT delete your question after it has been answered.