I need to transform using XSLT an XML input:
<CONTAINER>container1</CONTAINER>
<STOP>stop1</STOP>
<PO>po1</PO>
<PO>po2</PO>
<PO>po3</PO>
<CONTAINER>container2</CONTAINER>
<STOP>stop2</STOP>
<PO>po4</PO>
<PO>po5</PO>
<PO>po6</PO>
<STOP>stop3</STOP>
<PO>po7</PO>
<PO>po8</PO>
into
<CONTAINER>container1</CONTAINER>
<STOP>
<new_tag>Collapsed STOP</new_tag>
<PO>po1</PO>
<PO>po2</PO>
<PO>po3</PO>
</STOP>
<CONTAINER>container2</CONTAINER>
<STOP>
<new_tag>Collapsed STOP</new_tag>
<PO>po4</PO>
<PO>po5</PO>
<PO>po6</PO>
<STOP>stop3</STOP>
<PO>po7</PO>
<PO>po8</PO>
</STOP>
So basically I need to collapse all POs tag in a single STOP instead of having many STOPs, each one having a group of POs ad children.
Can someone help me on this? I'm very new to XSLT so I cannot fing a way to perform (if possible) this transformation.
答案 0 :(得分:2)
这个XSLT 2转换......
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes" encoding="utf-8" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="t">
<xsl:copy>
<xsl:for-each-group select="*" group-starting-with="CONTAINER">
<CONTAINER><xsl:value-of select="current-group()[self::CONTAINER]/text()" /></CONTAINER>
<STOP>
<new_tag>Collapsed STOP</new_tag>
<xsl:apply-templates select="current-group()
[not(self::CONTAINER)] (: Excluded because we have already dealt with CONTAINER. :)
[position() ge 2 ] (: Exclude the first STOP, because already dealt with. :)
" />
</STOP>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
...将转换此输入文档......
<t>
<CONTAINER>container1</CONTAINER>
<STOP>stop1</STOP>
<PO>po1</PO>
<PO>po2</PO>
<PO>po3</PO>
<CONTAINER>container2</CONTAINER>
<STOP>stop2</STOP>
<PO>po4</PO>
<PO>po5</PO>
<PO>po6</PO>
<STOP>stop3</STOP>
<PO>po7</PO>
<PO>po8</PO>
</t>
...进入此输出...
<t>
<CONTAINER>container1</CONTAINER>
<STOP>
<new_tag>Collapsed STOP</new_tag>
<PO>po1</PO>
<PO>po2</PO>
<PO>po3</PO>
</STOP>
<CONTAINER>container2</CONTAINER>
<STOP>
<new_tag>Collapsed STOP</new_tag>
<PO>po4</PO>
<PO>po5</PO>
<PO>po6</PO>
<STOP>stop3</STOP>
<PO>po7</PO>
<PO>po8</PO>
</STOP>
</t>
请参阅my answer here,了解有关xsl:for-each-group指令的更多信息。
答案 1 :(得分:0)
XSLT 1.0解决方案:
var videoLinks = [
....
];
var lastNumber = 0;
var randomNumber = function () {
var getRandomNumber = Math.floor(Math.random() * 5);
if(getRandomNumber != lastNumber){
var random = videoLinks[getRandomNumber];
document.getElementById("videoWrapper").innerHTML = random[0];
lastNumber = getRandomNumber;
}else{
randomNumber();
}
};
randomNumber(); // To call the function on load
关键部分在这里:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:template match="/root">
<root>
<xsl:apply-templates />
</root>
</xsl:template>
<xsl:template match="/root/CONTAINER">
<xsl:copy-of select="."/>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="/root/STOP">
<STOP>
<new_tag><xsl:value-of select="." /></new_tag>
<xsl:variable name="stopnum">
<xsl:number level="single" count="STOP" />
</xsl:variable>
<xsl:for-each select="following-sibling::PO[count(preceding-sibling::STOP) = $stopnum]">
<xsl:copy-of select="." />
</xsl:for-each>
</STOP>
</xsl:template>
<xsl:template match="text()" />
</xsl:transform>
我们设置一个变量,告诉我们已经处理的最后一个STOP节点的位置,然后选择我们的 <xsl:variable name="stopnum">
<xsl:number level="single" count="STOP" />
</xsl:variable>
<xsl:for-each select="following-sibling::PO[count(preceding-sibling::STOP) = $stopnum]">
中具有那么多for-each
个STOP节点的所有PO节点。 / p>
请注意,我已将XML封装在preceding-sibling
和<root>
节点中,以使其成为有效的XML。
输入:
</root>
输出:
<root>
<CONTAINER>container1</CONTAINER>
<STOP>stop1</STOP>
<PO>po1</PO>
<PO>po2</PO>
<PO>po3</PO>
<CONTAINER>container2</CONTAINER>
<STOP>stop2</STOP>
<PO>po4</PO>
<PO>po5</PO>
<PO>po6</PO>
<STOP>stop3</STOP>
<PO>po7</PO>
<PO>po8</PO>
</root>