XPath转换为小写不起作用

时间:2012-12-10 13:11:33

标签: .net xml xpath

xml文件看起来像

<employees>    
 <employee id='1'>
  <Profile_Name>admin</Profile_Name>
  <UserName>user</UserName>
 </employee>

 <employee id='2'>
  <Profile_Name>Admin</Profile_Name>
  <UserName>USER</UserName>
 </employee>

 <employee id='3'>
  <Profile_Name>Adminnn</Profile_Name>
  <UserName>userrrr</UserName>
 </employee>

这是我的xpath

         employees/employee
                     [not(Deleted)]
                       [Profile_Name[last()]
                          [translate(., 
                                     'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                                     'abcdefghijklmnopqrstuvwxyz'
                                     )
                          ]
                          =
                           'admin'or 
                           UserName[last()]
                                    [translate(.,
                                               'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                                                'abcdefghijklmnopqrstuvwxyz'
                                              )
                                    ]
                               =
                                'user'
                         ]

它应该选择employee不具有Deleted子元素的元素和Profile_Name = admin或UserName = user,而不管profileName和UserName

它运作正常,但不考虑字符大小。

它应该返回employee id = 1和2

3 个答案:

答案 0 :(得分:1)

你的翻译错误。代码生成的XPath表达式将测试类似

的内容
Profile_Name[last()][translate(.,'ABCDE...', 'abcde...')] = 'foo'

即。它将找到最后一个Profile_Name元素,检查该元素是否具有非空值,然后将该值(例如Foo)与字符串foo进行比较。相反,你需要

translate(Profile_Name[last()],'ABCDE...', 'abcde...') = 'foo'

对翻译的值而不是原始值进行比较。完整的表达式应该类似于

 var xpath = "/employees/employee[not(Deleted)][translate(Profile_Name[last()],'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')='" + ProfileName.ToLower() + "' or translate(UserName[last()],'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')='" + UserName.ToLower() + "']";

答案 1 :(得分:1)

现在你有了这个(格式正确使其可读):

           /employees/employee
                     [not(Deleted)]
                       [Profile_Name[last()]
                          [translate(Profile_Name[last()], 
                                     'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                                     'abcdefghijklmnopqrstuvwxyz'
                                     )
                          ]
                          =
                           'admin'or 
                           UserName[last()]
                                    [translate(.,
                                               'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                                                'abcdefghijklmnopqrstuvwxyz'
                                              )
                                    ]
                               =
                                'user'
                         ]";

显然是错误的 - 包含translate()的谓词过早关闭。

可能你想要这个

        /employees/employee
                     [not(Deleted)]
                           [translate(Profile_Name[last()], 
                                     'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                                     'abcdefghijklmnopqrstuvwxyz'
                                     )
                          =
                           'admin'
                         or 
                           translate(UserName[last()],
                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
                                      'abcdefghijklmnopqrstuvwxyz'
                                      )
                           =
                            'user'
                            ]

基于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:template match="/">
     <xsl:copy-of select=
     "/employees/employee
                     [not(Deleted)]
                           [translate(Profile_Name[last()],
                                     'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                                     'abcdefghijklmnopqrstuvwxyz'
                                     )
                          =
                           'admin'
                         or
                           translate(UserName[last()],
                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                                      'abcdefghijklmnopqrstuvwxyz'
                                      )
                           =
                            'user'
                      ]"/>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档(基于提供的转换,但添加了更多employee元素以提供更多必要的测试用例):

<employees>
    <employee id='1'>
        <Profile_Name>admin</Profile_Name>
        <UserName>user</UserName>
    </employee>
    <employee id='2'>
        <Profile_Name>Admin</Profile_Name>
        <UserName>USER</UserName>
    </employee>
    <employee id='3'>
      <Deleted/>
        <Profile_Name>Admin</Profile_Name>
        <UserName>user</UserName>
    </employee>
    <employee id='4'>
        <Profile_Name>Adminnn</Profile_Name>
        <UserName>userrrr</UserName>
    </employee>
</employees>

评估Xpath表达式并将此评估结果复制到输出中:

<employee id="1">
   <Profile_Name>admin</Profile_Name>
   <UserName>user</UserName>
</employee>
<employee id="2">
   <Profile_Name>Admin</Profile_Name>
   <UserName>USER</UserName>
</employee>

答案 2 :(得分:0)

.NET XSLT实现允许在样式表中编写自定义托管函数。对于小写(),它可以是:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:utils="urn:myExtension" exclude-result-prefixes="msxsl">

  <xsl:output method="xml" indent="yes"/>

  <msxsl:script implements-prefix="utils" language="C#">
    <![CDATA[
      public string ToLower(string stringValue)
      {
        string result = String.Empty;

        if(!String.IsNullOrEmpty(stringValue))
        {
          result = stringValue.ToLower(); 
        }

        return result;
      }
    ]]>
  </msxsl:script>

  <!-- using of our custom function -->
  <lowercaseValue>
    <xsl:value-of select="utils:ToLower($myParam)"/>
  </lowercaseValue>

假设,这可能很慢,但仍然可以接受。

不要忘记启用嵌入式脚本支持转换:

// Create the XsltSettings object with script enabled.
XsltSettings xsltSettings = new XsltSettings(false, true);

XslCompiledTransform xslt = new XslCompiledTransform();

// Load stylesheet
xslt.Load(xsltPath, xsltSettings, new XmlUrlResolver());