Как использовать функцию перевода в предикате аргумента XPath для XmlDocument.SelectNodes? - PullRequest
1 голос
/ 19 августа 2010

Я использую C # и .NET 2.0.

Учитывая приведенный ниже XML, я бы хотел получить XMLNodeList из <user> узлов, где <role> - "admin".1006 *

<users>
    <user>
        <name>John Doe</name>
        <roles>
            <role>superadmin</role>
            <role>admin</role>
        </roles>
    </user>
    <user>
        <name>Jane Doe</name>
        <roles>
            <role>superadmin</role>
            <role>admin</role>
        </roles>
    </user>
    <user>
        <name>Rob Doe</name>
        <roles>
            <role>support</role>
        </roles>
    </user>
 </users>

Предположим, roleName = "admin".Это работает, но с учетом регистра.

userNodesForRole = _document.SelectNodes("//users/user[roles[role='" + roleName + "']]");

Я хочу сделать это без учета регистра.Я знаю, что не могу использовать функцию matches, потому что .NET 2.0 (а может и выше?) Не поддерживает XPath 2.0.Итак, я сделал это:

// abc...xyz is the string literal of the entire alphabet, of course
userNodesForRole = _document.SelectNodes("//users/user[roles[translate(role,'abc..xyz','ABC...XYZ')='" + roleName.ToUpper() + "']]", _xmlNamespaceManager);

Однако я не вернул ни одного узла.Может кто-нибудь сказать, пожалуйста, что я делаю не так?

1 Ответ

1 голос
/ 19 августа 2010

_document.SelectNodes ("// users / user [role [translate (role, abc..xyz ',' ABC ... XYZ ') ​​='" + roleName.ToUpper () + "']] ", _xmlNamespaceManager);

Это вычисляет выражение XPath наподобие следующего:

  //users/user
           [roles
             [translate(role,
                        'abcdefghijklmnopqrstuvxyz',
                        'ABCDEFGHIJKLMNOPQRSTUVXYZ'
                        )
             =
              'ADMIN'
              ]
           ]

и приведенное выше выражение XPath при оценке в предоставленном документе XML :

<users>
    <user>
        <name>John Doe</name>
        <roles>
            <role>admin</role>
        </roles>
    </user>
    <user>
        <name>Jane Doe</name>
        <roles>
            <role>admin</role>
        </roles>
    </user>
    <user>
        <name>Rob Doe</name>
        <roles>
            <role>support</role>
        </roles>
    </user>
 </users>

выбирает следующие узлы:

<user>
    <name>John Doe</name>
    <roles>
        <role>admin</role>
    </roles>
</user>

<user>
    <name>Jane Doe</name>
    <roles>
        <role>admin</role>
    </roles>
</user>

Выражение XPath не будет выбирать нужные элементы, если существует элемент roles, которыйимеет более одного role дочернего элемента, и элемент <role>admin</role> не является первым role дочерним элементом его родительского элемента.

Выражение XPath, которое выбирает требуемые элементы даже в этом случае:

  //users/user
           [roles/role
             [translate(.,
                        'abcdefghijklmnopqrstuvxyz',
                        'ABCDEFGHIJKLMNOPQRSTUVXYZ'
                        )
             =
              'ADMIN'
              ]
           ]

Может быть множество причин, по которым первое выражение вызывает исключение или не выбирает нужные узлы.Чтобы выяснить точную причину, напечатайте построенное выражение XPath и предоставьте его здесь.

Обновление : @ck теперь предоставил свой настоящий XML-документ и действительно, вВ реальном XML-документе дочерние элементы role (элементы <role>admin</role>) не являются первыми дочерними элементами role их родителей.

Так что мои догадки и объяснения были правильными.

...