2

我发现在 Xpath 表达式中使用“数字”函数时,该函数仅使用序列中的第一个节点。问题的一个例子:

using System.Xml;
using System;
namespace ConsoleApplication1
{
    public class Program
    {
        public static void Main()
        {
            XmlDocument doc = new XmlDocument();            
            doc.LoadXml(
@"<baseball>
    <games>
        <game>
            <id>1</id>
            <stadiumId>7</stadiumId>
            <attendance>4999</attendance>
        </game>
        <game>
            <id>2</id>
            <stadiumId>5</stadiumId>
            <attendance>600</attendance>
        </game>
        <game>
            <id>3</id>
            <stadiumId>5</stadiumId>
            <attendance>789</attendance>
        </game>
    </games>
    <stadiums>
        <stadium><id>5</id><capacity>1000</capacity></stadium>
        <stadium><id>7</id><capacity>5000</capacity></stadium>
        <stadium><id>9</id><capacity>560</capacity></stadium>
    </stadiums>
</baseball>");

            printNodes("what stadiums had games occur in them?",
                doc.SelectNodes("/baseball/stadiums/stadium[./id/text()=/baseball/games/game/stadiumId/text()]"));

            printNodes("what stadiums had games occur in them? this time converting to numbers before doing comparison",
                doc.SelectNodes("/baseball/stadiums/stadium[number(./id/text())=number(/baseball/games/game/stadiumId/text())]"));
        }//Main

        private static void printNodes(string description, XmlNodeList nodeList)
        {
            Console.WriteLine("-----" + description + "-------");
            foreach (XmlNode node in nodeList)
                Console.WriteLine(node.OuterXml);
            Console.WriteLine("-------------------");
        }       
    }//class
}//namespace

输出是:

-----what stadiums had games occur in them?-------
<stadium><id>5</id><capacity>1000</capacity></stadium>
<stadium><id>7</id><capacity>5000</capacity></stadium>
-------------------
-----what stadiums had games occur in them? this time converting to numbers before doing comparison-------
<stadium><id>7</id><capacity>5000</capacity></stadium>
-------------------

它仅在第二个输出中返回体育场 7 的原因(尽管 Xpath 查询在逻辑上相同)是因为第一个棒球/游戏/游戏节点的 StadiumId 为 7。没有评估其他游戏节点。

这是数字功能的预期功能吗?有没有解决的办法?

4

2 回答 2

2

第一:number按设计仅转换节点集中的第一个元素 - 请参阅XPath 规范中的数字

第二: =在 XPath 中更像是“任意对匹配”而不是“两边都相等”。因此,您的第一个陈述是正确的,因为“游戏/游戏”中有一个元素与“id”匹配“体育场”,第二个无法按预期工作,因为“游戏/游戏/体育场Id”节点列表由“数字”转换" 函数只是列表中第一个的 ID(见上文)。

如果您要编写许多 XPath 表达式,请阅读规范,至少是定义“=”如何工作的布尔部分。

于 2013-04-03T17:29:04.203 回答
2

如果你真的想比较数字,在 XPath 2.0 中你可以使用

  /*/stadiums/*
        [xs:integer(id) = /*/games/*/stadiumId/xs:integer(.)]

基于 XSLT 2.0 的验证

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:sequence select=
  "/*/stadiums/*
         [xs:integer(id) = /*/games/*/stadiumId/xs:integer(.)]"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<baseball>
    <games>
        <game>
            <id>1</id>
            <stadiumId>7</stadiumId>
            <attendance>4999</attendance>
        </game>
        <game>
            <id>2</id>
            <stadiumId>5</stadiumId>
            <attendance>600</attendance>
        </game>
        <game>
            <id>3</id>
            <stadiumId>5</stadiumId>
            <attendance>789</attendance>
        </game>
    </games>
    <stadiums>
        <stadium>
            <id>5</id>
            <capacity>1000</capacity>
        </stadium>
        <stadium>
            <id>7</id>
            <capacity>5000</capacity>
        </stadium>
        <stadium>
            <id>9</id>
            <capacity>560</capacity>
        </stadium>
    </stadiums>
</baseball>

对 XPath 表达式求值,并将该求值的结果(选定元素)复制到输出

<stadium>
            <id>5</id>
            <capacity>1000</capacity>
</stadium>
<stadium>
            <id>7</id>
            <capacity>5000</capacity>
</stadium>
于 2013-04-04T04:11:11.910 回答