我想知道语句[@id=current()/@id]
只有在id是整数的情况下才能工作:
<elem id="1">
<elem id="1">
但如果我有:
<elem id="AAA">
<elem id="AAA">
它不起作用。
我的XSL失败的地方:
<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:tn="http://"
exclude-result-prefixes="xsl xs fn tn">
<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="genre/*">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="
book[@id=current()/@id][@action='extend']
[not( preceding-sibling::book[@id=current()/@id][@action='borrow'])]" />
<xsl:for-each-group
select="book[@id=current()/@id][@action='borrow']
|
book[@id=current()/@id][@action='extend']
[preceding-sibling::book[@id=current()/@id][@action='borrow']]"
group-starting-with="book[@action='borrow']">
<xsl:for-each select="current-group()[1]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:call-template name="merge-books-deeply">
<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="
node()[ not( self::book[@id=current()/@id][@action=('borrow','extend')])]" />
</xsl:copy>
</xsl:template>
<xsl:function name="tn:children-on-path" as="element()*">
<xsl:param name="base" as="element()*" />
<xsl:param name="path" as="xs:string*" />
<xsl:choose>
<xsl:when test="fn:empty($base)">
<xsl:sequence select="()" />
</xsl:when>
<xsl:when test="fn:empty($path)">
<xsl:copy-of select="$base/*" />
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="tn:children-on-path(
$base/*[name()=$path[1]],
$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="tn:children-on-path($books,$name-path)"
group-by="name()">
<xsl:for-each select="current-group()[last()]" >
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:call-template name="merge-books-deeply">
<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>
输入样本的工作地点:
<root>
<library id="L1">
<genre id="a">
<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="extend">
<attributes>
<length>99</length>
<condition>not-ok</condition>
</attributes>
<other>y</other>
</book>
</shelf1>
<shelf1 id="b">...
</shelf1>
</genre>
<genre id="b">...
</genre>
</library>
</root>
如果我将图书的ID更改为1a
:
<root>
<library id="L1">
<genre id="a">
<shelf1 id="1">
<book id="1a" action="borrow">
<attributes>
<user>John</user>
</attributes>
<other1>y</other1>
</book>
<book id="1a" action="extend">
<attributes>
<user>Woo</user>
<length>3</length>
</attributes>
<other2>y</other2>
</book>
<book id="1a" action="extend">
<attributes>
<length>2</length>
<condition>ok</condition>
</attributes>
<other3>y</other3>
</book>
<book id="2" action="extend">
<attributes>
<length>99</length>
<condition>not-ok</condition>
</attributes>
<other>y</other>
</book>
</shelf1>
<shelf1 id="b">...
</shelf1>
</genre>
<genre id="b">...
</genre>
</library>
</root>
我的错误输出:(根本不合并)
<root>
<library id="L1">
<genre id="a">
<shelf1 id="1">
<book id="a1" action="borrow">
<attributes>
<user>John</user>
</attributes>
<other1>y</other1>
</book>
<book id="a1" action="extend">
<attributes>
<user>Woo</user>
<length>3</length>
</attributes>
<other2>y</other2>
</book>
<book id="a1" action="extend">
<attributes>
<length>2</length>
<condition>ok</condition>
</attributes>
<other3>y</other3>
</book>
<book id="2" action="extend">
<attributes>
<length>99</length>
<condition>not-ok</condition>
</attributes>
<other>y</other>
</book>
</shelf1>
<shelf1 id="b">...
</shelf1>
</genre>
<genre id="b">...
</genre>
</library>
</root>
预期产出:
<root>
<library id="L1">
<genre id="a">
<shelf1 id="1">
<book id="1a" action="borrow">
<attributes>
<user>Woo</user>
<length>2</length>
<condition>ok</condition>
</attributes>
<other1>y</other1>
</book>
<book id="2" action="extend">
<attributes>
<length>99</length>
<condition>not-ok</condition>
</attributes>
<other>y</other>
</book>
</shelf1>
<shelf1 id="b">...
</shelf1>
</genre>
<genre id="b">...
</genre>
</library>
</root>
对于每个具有action = borrow的节点,后跟一个或多个带有action = extend
的节点将其合并到具有action = borrow的节点。
将子属性合并在一起,使其具有最新值的兄弟姐妹的所有唯一属性。
保持其他孩子不变
合并仅发生在具有相同ID的节点上。
感谢。 问候, 约翰
答案 0 :(得分:3)
也许您遇到了上下文问题。比较应该有效。这是一个例子......
XML输入
<tests>
<test>
<elem id="1"/>
<elem id="1"/>
</test>
<test>
<elem id="AAA"/>
<elem id="AAA"/>
</test>
<test>
<elem id="BBB"/>
<elem id="CCC"/>
</test>
<test>
<elem id="2"/>
<elem id="3"/>
</test>
</tests>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="elem[1]">
<xsl:text>Comparing id </xsl:text>
<xsl:value-of select="concat('"',@id,'"
')"/>
<xsl:value-of select="concat('	',
boolean(following-sibling::*[@id=current()/@id]),
'
')"/>
</xsl:template>
</xsl:stylesheet>
<强>输出强>
Comparing id "1"
true
Comparing id "AAA"
true
Comparing id "BBB"
false
Comparing id "2"
false
修改强>
在查看更新后的示例后,它看起来肯定是一个上下文问题。看一下模板的开头:
<xsl:template match="genre/*">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="
book[@id=current()/@id][@action='extend']
[not( preceding-sibling::book[@id=current()/@id][@action='borrow'])]" />
请注意,匹配为genre/*
;这是当前的背景。您的输入将是shelf1
。然后,第二个xsl:apply-templates
的选择以book[@id=current()/@id]
开头。对我来说,如果它book
属性等于id
id
属性,则会选择shelf1
。要对此进行测试,您还可以将id
的{{1}}更改为shelf1
,这可能会有效。 (这就是第一个例子有效的原因; 1a
和id
的{{1}}匹配。
我现在无法测试这个理论,但我认为这就是比较不起作用的原因。 (它正在运作,你只是没有比较你认为你在比较的东西。)
答案 1 :(得分:1)
字符串比较不需要显式字符串转换。换句话说,它应该像你写的一样工作。这是一个例子:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="elem">
<xsl:if test="count(../elem[@id=current()/@id]) > 1">
<xsl:value-of select="@id"/>: has dup
</xsl:if>
</xsl:template>
</xsl:stylesheet>
应用于此输入时:
<r>
<elem id="AAA">one</elem>
<elem id="AAA">two</elem>
<elem id="ZZZ">three</elem>
</r>
生成以下输出:
AAA: has dup
AAA: has dup
否则,如果要比较的对象中至少有一个是数字,那么 将要比较的每个对象转换为数字,就像通过应用一样 数字功能。否则,要比较的两个对象都是 通过应用字符串函数转换为字符串。