在XPath中使用translate函数会产生错误

时间:2012-07-06 15:22:43

标签: xml xpath

我必须进行不区分大小写的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'和col / text()='fep'] [not(* [@ iskey] [local-name()!='col'])] “;

现在我的要求是col值在任何情况下都可以是大写或小写,所以我想要改变我的xpath,它返回结果,而不管xml中存在数据的情况。  如果用户提供援助或援助或aiD,则返回结果。

2 个答案:

答案 0 :(得分: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文档时,它包含任何“援助”大写的元素名称 - 例如:

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

答案 1 :(得分:0)

请尝试使用union translate()

,而不是使用(aid|AID)

新xpath:

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