【问题标题】:Using translate function in XPath gives error在 XPath 中使用 translate 函数会出错
【发布时间】:2019-10-14 12:53:48
【问题描述】:

我必须进行不区分大小写的 XML 搜索。我编写了运行良好的 XPath 表达式,但是当我在 XPath 表达式中使用 translate 函数时出现错误。以下是运行良好的 XPath 表达式:

string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string lower = "abcdefghijklmnopqrstuvwxyz";

string xpath = "/data/item[AID/@iskey='true' and AID/text() = 'fep'][not(*[@iskey][local-name() != 'AID' ])]";       

string xpath1 = "/data/item[translate('Aid','" + upper + "','" + lower + "')]";

这是我的 XML:

<?xml version="1.0" encoding="utf-8"?>
<data>
<item>
 <AID iskey="true">fep</AID>
  <account>MS</account>
  </item>
</data>

我想将translate 函数放在第一个 XPath 表达式中,如下所示:

 string xpath = "/data/item[translate('AID','" + upper + "','" + lower + "')/@iskey='true' and translate('AID','" + upper + "','" + lower + "')/text() = 'fep'][not(*[@iskey][local-name() != translate('aid','" + upper + "','" + lower + "') ])]";

当我这样做时,我收到以下错误:

表达式必须计算为节点集。

这个 xpath 对我来说很好用。

 string col="AID"; 
 string xpath = "/data/item[col/@iskey='true' and col/text() = 'fep'][not(*[@iskey][local-name() != 'col' ])]";   

现在我的要求是 col 值在任何情况下都可以是大写或小写,因此我希望更改我的 xpath,无论在哪种情况下,xml 中都存在数据,它都会返回结果。 如果用户提供援助或援助或援助,它会返回结果。

【问题讨论】:

    标签: xml xpath


    【解决方案1】:

    错误是由于在您的 XPath 表达式中您有这样的位置步骤:

    item['aid'/@isKey = 'true' ...]
    

    子表达式:

    'aid'/@isKey
    

    在 XPath 中在语法上是非法的,因为 / 运算符的左侧必须是一个节点集——这里它只是一个字符串。

    你想要一个这样的 XPath 表达式——而不是你目前正在生成的那个

    /data/item
           [*[translate(name(), 'aid', 'AID') = 'AID']/@iskey='true'
          and
            *[translate(name(), 'aid', 'AID') = 'AID'] = 'fep'
             ]
              [not(*[@iskey]
                    [translate(name(), 'aid', 'AID') != 'AID']
                 )
             ]
    

    基于 XSLT 的验证

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>
     <xsl:strip-space elements="*"/>
    
     <xsl:variable name="vLower" select="'aid'"/>
     <xsl:variable name="vUpper" select="'AID'"/>
    
     <xsl:template match="node()|@*">
         <xsl:copy-of select=
          "/data/item
               [*[translate(name(), 'aid', 'AID') = 'AID']/@iskey='true'
              and
                *[translate(name(), 'aid', 'AID') = 'AID'] = 'fep'
                 ]
                  [not(*[@iskey]
                        [translate(name(), 'aid', 'AID') != 'AID']
                     )
                 ]
          "/>
     </xsl:template>
    </xsl:stylesheet>
    

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

    <data>
        <item>
            <AID iskey="true">fep</AID>
            <account>MS</account>
        </item>
    </data>
    

    计算 XPath 表达式并将选定节点(本例中只有一个)复制到输出

    <item>
       <AID iskey="true">fep</AID>
       <account>MS</account>
    </item>
    

    更新

    OP 难以理解此解决方案。这是一个向他展示该解决方案适用于字符串“aid”的任何大写的示例:

    当上述转换应用于 XML 文档时,该文档包含的元素名称为“aid”的任何大写形式——例如:

    <data>
        <item>
            <aId iskey="true">fep</aId>
            <account>MS</account>
        </item>
    </data>
    

    再次产生预期的结果

    <item>
       <aId iskey="true">fep</aId>
       <account>MS</account>
    </item>
    

    更新 2

    OP 仍然不理解解决方案,并声称对于特定的 XML 文档——下面提供——“我使用你的表达式它返回 null”

    这是 OP 评论中提供的 XML 文档:

    <data>
        <item>
            <aId iskey="true">fep</aId>
            <account>FG</account>
        </item>
    </data>
    

    当针对该文档运行相同的 XSLT 验证时,再次选择并输出正确的元素

    <item>
       <aId iskey="true">fep</aId>
       <account>FG</account>
    </item>
    

    【讨论】:

    • 是的。你检查这个表达式吗?我仍然遇到同样的错误
    • @WaqarJanjua:查看我更新的答案——在 XSLT 中使用时可以正常工作。
    • 是的,它正在工作。但是有一个问题是你把翻译功能等于'AID',这是固定的吗? .它可以是援助或援助或援助等,所以当我将其更改为“援助”时,表达式返回空值。它希望它不区分大小写。
    • @WaqarJanjua:代码是正确的,你需要理解它。在 XPath 表达式中,“AiD”被翻译为“AID”​​,这等于“AID”​​,因此比较的结果为真。处理“aID”时完全相同。我建议您还使用不同的输入运行转换,以亲自查看它在所有情况下都能正常工作。
    • @WaqarJanjua:您最后的评论明确表明您理解代码。正如我所说,尝试使用每个可能的源 XML 文档进行转换,您可以看到它在每种情况下都能正常工作。
    【解决方案2】:

    不要使用translate(),而是尝试使用联合:(aid|AID)

    新的 xpath:

    /data/item[(aid|AID)/@iskey='true' and (aid|AID)/text() = 'fep'][not(*[@iskey][local-name() != 'AID' and local-name() != 'aid'])]
    

    【讨论】:

    • 不是固定的,可以是Aid、aiD、AId、AiD等。我想要不区分大小写的xpath。
    猜你喜欢
    • 1970-01-01
    • 2018-12-04
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    相关资源
    最近更新 更多