2

在 xpath 中使用“except”时遇到问题。这是问题代码块。(我试图在不掩盖整个问题的情况下尽可能简化)。:

<!--First, create a variable containing some nodes that we want to filter out. 
 (I'm gathering elements that are missing child VALUE elements
 and whose child DOMAIN and VARIABLE elements only occur once
 in the parent list of elements.)
 I've confirmed that this part does generate the nodes I want,
 but maybe this is the incorrect result structure?-->

<xsl:variable name="badValues">
 <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>

<!--Next Loop over the original nodes, minus those bad nodes.
 For some reason, this loops over all nodes and does not filter out the bad nodes.-->

<xsl:for-each select="$root/A except $badValues/A"> ...
4

1 回答 1

1

当您创建一个xsl:variable不使用且不使用@select指定类型时@as,它会将变量创建为临时树

您想要创建一系列节点,以便在except运算符中比较它们时,它们被“视为”为相同的节点。您可以通过指定as="node()*"forxsl:variable和使用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>

或者,如果您要使用 a@select并消除它,xsl:for-each它也可以工作。正如Martin Honnen建议的那样,您可以使用xsl:key并选择如下值:

 <xsl:key name="by-dom-and-var" match="A" use="concat(DOMAIN, '|', VARIABLE)"/>

然后将您的 badValues 更改为:

<xsl:variable name="badValues" 
     select="$root/A[not(VALUE)]
                    [count(key('by-dom-and-var', 
                               concat(DOMAIN, '|', VARIABLE))/VARIABLE) = 1]"/>>

generate-id()您可以通过执行此样式表在迭代项目时使用该函数来查看节点身份的差异:

<?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>

针对此 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>

它产生以下输出:

<rootA>d1e3, d1e15, d1e24, d1e33, d1e42</rootA>
<originalBadValues>d2e1, d2e9</originalBadValues>
<badValues>d1e24, d1e33</badValues>
<final>d1e3, d1e15, d1e42</final>
于 2013-05-25T01:22:11.333 回答