Xslt 使用时的结构要求;除「;在XPATH/XSL中
在xpath中使用“except”时遇到问题。下面是一段问题代码。(我试图在不掩盖整个问题的情况下尽可能简化。)Xslt 使用时的结构要求;除「;在XPATH/XSL中,xslt,xpath,xslt-2.0,xpath-2.0,except,Xslt,Xpath,Xslt 2.0,Xpath 2.0,Except,在xpath中使用“except”时遇到问题。下面是一段问题代码。(我试图在不掩盖整个问题的情况下尽可能简化。) ... 当您创建xsl:variable而不使用@select并且不将@指定为类型时,它会将变量创建为一个变量 您希望创建一系列节点,以便在操作符中对它们进行比较时,“看到”它们是相同的节点。您可以通过为xsl:variable指定as=“node()*”,并使用xsl:sequence而不是xsl:copy of: <xsl:variable name="badValues
...
当您创建xsl:variable
而不使用@select
并且不将@指定为类型时,它会将变量创建为一个变量
您希望创建一系列节点,以便在操作符中对它们进行比较时,“看到”它们是相同的节点。您可以通过为xsl:variable
指定as=“node()*”
,并使用xsl:sequence
而不是xsl:copy of
:
<xsl:variable name="badValues" as="node()*">
<xsl:for-each select="$root/A[not(VALUE)]">
<xsl:choose>
<xsl:when test="count($root/A[DOMAIN=current()/DOMAIN
and VARIABLE=current()/VARIABLE])=1">
<xsl:sequence select="."/>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
然后将您的值更改为:
<xsl:variable name="badValues"
select="$root/A[not(VALUE)]
[count(key('by-dom-and-var',
concat(DOMAIN, '|', VARIABLE))/VARIABLE) = 1]"/>>
针对此XML文件执行:
<doc>
<A>
<VALUE>skip me</VALUE>
<DOMAIN>a</DOMAIN>
<VARIABLE>a</VARIABLE>
</A>
<A>
<DOMAIN>a</DOMAIN>
<VARIABLE>a</VARIABLE>
</A>
<A>
<DOMAIN>b</DOMAIN>
<VARIABLE>b</VARIABLE>
</A>
<A>
<DOMAIN>c</DOMAIN>
<VARIABLE>c</VARIABLE>
</A>
<A>
<DOMAIN>a</DOMAIN>
<VARIABLE>a</VARIABLE>
</A>
</doc>
跳过我
A.
A.
A.
A.
B
B
C
C
A.
A.
它产生以下输出:
<rootA>d1e3, d1e15, d1e24, d1e33, d1e42</rootA>
<originalBadValues>d2e1, d2e9</originalBadValues>
<badValues>d1e24, d1e33</badValues>
<final>d1e3, d1e15, d1e42</final>
d1e3、d1e15、d1e24、d1e33、d1e42
d2e1,d2e9
d1e24,d1e33
d1e3、d1e15、d1e42
关于新创建节点的临时树的良好解释。不过,对于解决方案,我建议通过定义一个键
,然后简单地执行
,来简化代码。这一点很好。我在答案中添加了一个解释,即如果使用@select
,变量也会被创建为一个序列。首先,我想指出,..
必须更改为..
,我只想让其他可能看到这一点的人明白这一点。非常感谢你们的回答和建议。这些不仅解决了我的问题,而且还简化了我的其他代码,使我的生活更轻松。我一直在试图找到一种不用循环在xsl中进行“连接”的方法,看起来使用键可以解决这个问题。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:variable name="root" select="*" as="item()*"/>
<xsl:variable name="originalBadValues">
<xsl:for-each select="$root/A[not(VALUE)]">
<xsl:choose>
<xsl:when test="count($root/A[DOMAIN=current()/DOMAIN
and VARIABLE=current()/VARIABLE])=1">
<xsl:copy-of select="."/>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="badValues" as="node()*">
<xsl:for-each select="$root/A[not(VALUE)]">
<xsl:choose>
<xsl:when test="count($root/A[DOMAIN=current()/DOMAIN
and VARIABLE=current()/VARIABLE])=1">
<xsl:sequence select="."/>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<!--These are the generated ID values of all the A elements-->
<rootA>
<xsl:value-of select="$root/A/generate-id()"
separator=", "/>
</rootA>
<!--These are the generated ID values for
the original $badValues/A -->
<originalBadValues>
<xsl:value-of select="$originalBadValues/A/generate-id()"
separator=", " />
</originalBadValues>
<!--These are the generated ID values for
the correct selection of $badValues-->
<badValues>
<xsl:value-of select="$badValues/generate-id()"
separator=", " />
</badValues>
<!--The generated ID values for the result of
the except operator filter-->
<final>
<xsl:value-of select="($root/A except $badValues)/generate-id()"
separator=", "/>
</final>
</xsl:template>
</xsl:stylesheet>
<doc>
<A>
<VALUE>skip me</VALUE>
<DOMAIN>a</DOMAIN>
<VARIABLE>a</VARIABLE>
</A>
<A>
<DOMAIN>a</DOMAIN>
<VARIABLE>a</VARIABLE>
</A>
<A>
<DOMAIN>b</DOMAIN>
<VARIABLE>b</VARIABLE>
</A>
<A>
<DOMAIN>c</DOMAIN>
<VARIABLE>c</VARIABLE>
</A>
<A>
<DOMAIN>a</DOMAIN>
<VARIABLE>a</VARIABLE>
</A>
</doc>
<rootA>d1e3, d1e15, d1e24, d1e33, d1e42</rootA>
<originalBadValues>d2e1, d2e9</originalBadValues>
<badValues>d1e24, d1e33</badValues>
<final>d1e3, d1e15, d1e42</final>