我有这个输入文件:
<root>
<library id="L1">
<shelf1 id="1">
<book id="1" action="borrow">
<attributes>
<user>John</user>
</attributes>
<other1>y</other1>
</book>
<book id="1" action="extend">
<attributes>
<user>Woo</user>
<length>3</length>
</attributes>
<other2>y</other2>
</book>
<book id="1" action="extend">
<attributes>
<length>2</length>
<condition>ok</condition>
</attributes>
<other3>y</other3>
</book>
<book id="2" action="borrow">...</book>
</shelf1>
<shelf2>...</shelf2>
</library>
</root>
预期产出:
<root>
<library id="L1">
<shelf1 id="1">
<book id="1" action="borrow">
<attributes>
<user>Woo</user>
<length>2</length>
<condition>ok</condition>
</attributes>
<other1>y</other1>
<other2>y</other2>
<other3>y</other3>
</book>
<book id="2" action="borrow">...</book>
</shelf1>
<shelf2>...</shelf2>
</library>
</root>
我的XSL:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="library/*/*[1]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<attributes>
<xsl:for-each-group select="attributes/*" group-by="name()">
<xsl:sort select="current-grouping-key()"/>
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</attributes>
<xsl:apply-templates select="*[not(self::attributes)]"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"library/*/*
[@action='extend' and following-sibling::*[1][@action='extend']
or preceding-sibling::*[@action='borrow']]"/>
</xsl:stylesheet>
对于action=borrow
后跟一个或多个action=extend
action=borrow
的节点。 attributes
个孩子合并在一起,使其具有最新值的兄弟姐妹的所有独特属性。请告诉我如何使用XSLT 2.0修复此转换?
非常感谢。
亲切的问候, 约翰
答案 0 :(得分:3)
你问了很多类似的问题。也许是时候买书并花几天时间阅读?这可能是我最后一次回答你的类似问题。您应该能够从答案中学习,这样您就不必提出类似的问题。如果你不学习,你必须问自己:“什么阻碍了你?”
任何方式,让我们来看看这个样式表。在解释中,我将点作为xml或xpath注释中的数字引用。例如,第1点划分为&lt;! - 1 - &gt; ,或者如果在xpath表达式中,则(:1:)。显然,删除生产的评论。
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:John="http://stackoverflow.com/questions/11463900"
exclude-result-prefixes="xsl xs fn John">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(local-name(),'shelf')] (: 1 :)">
<xsl:copy>
<xsl:apply-templates select="@*" />
<!-- 2 -->
<xsl:apply-templates select="
book[@action='extend'] (: 3 :)
[not( preceding-sibling::book[@action='borrow'])] (: 4 :)" />
<!-- 5 -->
<xsl:for-each-group
select="book[@action='borrow'] (: 6 :)
| (: 7 :)
book[@action='extend']
[preceding-sibling::book[@action='borrow']] (: 8 :)"
group-starting-with="book[@action='borrow']">
<xsl:for-each select="current-group()[1]">
<xsl:copy> <!-- 9 -->
<xsl:apply-templates select="@*" />
<xsl:call-template name="merge-books-deeply"> <!-- 10 -->
<xsl:with-param name="books" select="current-group()" />
<xsl:with-param name="name-path" select="()" />
</xsl:call-template>
</xsl:copy>
</xsl:for-each>
</xsl:for-each-group>
<xsl:apply-templates select=" (: 11 :)
node()[ not( self::book[@action=('borrow','extend')])]" />
</xsl:copy>
</xsl:template>
<xsl:function name="John:children-on-path" as="element()*">
<xsl:param name="base" as="element()*" /> <!-- 12 -->
<xsl:param name="path" as="xs:string*" /> <!-- 13 -->
<xsl:choose>
<xsl:when test="fn:empty($base)">
<xsl:sequence select="()" />
</xsl:when>
<xsl:when test="fn:empty($path)">
<xsl:copy-of select="$base/*" /> <!-- 14 -->
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="John:children-on-path(
$base/*[name()=$path[1]], (: 15 :)
$path[position() ne 1])" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:template name="merge-books-deeply">
<xsl:param name="books" as="element()*" />
<xsl:param name="name-path" as="xs:string*" />
<xsl:for-each-group
select="John:children-on-path($books,$name-path)"
group-by="name()"> <!-- 16 -->
<xsl:for-each select="current-group()[last()]" > <!-- 17 -->
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:call-template name="merge-books-deeply"> <!-- 18 -->
<xsl:with-param name="books" select="$books" />
<xsl:with-param name="name-path" select="$name-path,name()" />
</xsl:call-template>
<xsl:apply-templates select="text()" />
</xsl:copy>
</xsl:for-each>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>