Вы говорите, что ваш XML - это фрагмент кода.Я рискну предположить, что он содержится в элементе, который связывает префикс пространства имен по умолчанию с нетривиальным URI, и именно поэтому вы не получаете результатов от своего итератора.
Ваш кодработал для меня, с документом XML, как указано выше.Я запустил код и получил один элемент из итератора.Затем я взял ваш XML-документ и обернул его в корневой элемент, который связывает префикс пространства имен по умолчанию с готовым, но нетривиальным URI:
<SomeRootElement xmlns="http://schemas.blahblahblah.com/example">
<ItemAttributes>
<!-- rest of your document omitted -->
</ItemAttributes>
</SomeRootElement>
Затем я не получил результатов от итератора.
Затем я создал XmlNamespaceManager , который сопоставил префикс (я выбрал pfx
) с URI пространства имен, использованным выше:
XmlNamespaceManager mgr = new XmlNamespaceManager(new NameTable());
mgr.AddNamespace("pfx", "http://schemas.blahblahblah.com/example");
Затем я установил этот менеджер пространства имен какконтекст пространства имен для выражения XPath и добавил префикс pfx
к именам в вашем выражении XPath:
XPathExpression expr;
expr = nav.Compile("//pfx:ItemAttributes[contains(pfx:ProductGroup, 'Book')]");
expr.SetContext(mgr);
XPathNodeIterator iterator = nav.Select(expr);
Затем я получил один элемент из итератора, как и ожидалось.
XPath может быть немного смешным с пространствами имен.Я попытался связать пустой префикс ""
с URI, чтобы я мог использовать ваше выражение XPath без изменений, но это не сработало.Одна вещь, которую я обнаружил в XPath ранее: всегда связывать URI пространства имен с префиксами XPath, даже если исходный документ XML связывает префикс пространства имен по умолчанию.Нефиксированные имена в XPath всегда находятся в пространстве имен «null».
Я не особо задумывался о том, как сопоставить префиксы пространства имен с URI с помощью XPath в .NET, и, вероятно, есть более эффективные способы сделать это.это то, что я собрал после быстрого поиска в Google и чтения MSDN.
EDIT : цель моего ответа состояла в том, чтобы объяснить, почему ваш код, использующий XPath, не работал.Вы не поняли, почему не получили результатов от итератора.Я подозревал, что вы не дали мне полный XML-документ, и что в той части документа, которой вы не поделились с нами, был дан ответ.
В конечном счете, я полагаю, что ваш исходный код этого не сделал 'работает из-за пространств имен XML .Когда я пишу это изменение, я могу получить только ошибку «Запрос истек» из URL-адресов в вашей ветке комментариев с помощью LB, поэтому я больше не могу тестировать те же данные, которые вы используете.Однако этот запрос об ошибке начинается следующим образом:
<?xml version="1.0"?>
<ItemLookupErrorResponse xmlns="http://ecs.amazonaws.com/doc/2011-08-01/">
Атрибут xmlns
помещает элемент и каждый элемент, содержащийся в нем, в пространство имен .Каждое пространство имен идентифицируется URI, и вместе URI и имя элемента идентифицируют этот элемент.
Возможно, успешный запрос может иметь один и тот же атрибут.Тем не менее, ответ LB использует другое пространство имен, поэтому я не уверен.В остальной части этого редактирования я должен предположить, что успешный запрос содержит то же пространство имен, что и неудачное.
Из-за этого пространства имен элемент <ItemAttributes>
в этом XML
<ItemLookupResponse xmlns="http://ecs.amazonaws.com/doc/2011-08-01/">
<ItemAttributes />
</ItemLookupResponse>
и внутри этого XML
<ItemAttributes />
не совпадают.Первый находится в пространстве имен http://ecs.amazonaws.com/doc/2011-08-01/
, а второй - в пространстве имен, обозначенном пустой строкой.Это пустое пространство имен является пространством имен по умолчанию, если оно не было задано другим способом.
Поскольку два элемента ItemAttributes
имеют разные пространства имен, они не одинаковы.
Такжеизменяя пространство имен элементов с помощью xmlns="..."
, вы также можете связать (или bind ) префикс с пространством имен.Это делается путем указания префикса, который вы хотите связать с пространством имен, в атрибуте xmlns
, используя такой атрибут, как xmlns:prefix="some-uri"
.Этот префикс затем помещается в элемент XML перед локальным именем, например <prefix:SomeElement ... />
.Это помещает элемент SomeElement
в пространство имен, связанное с URI some-uri
.
Поскольку элементы идентифицируются с помощью локального имени и URI пространства имен, следующие два фрагмента XML равны, хотя один использует префикс идругой - нет:
<ItemLookupResponse xmlns="http://ecs.amazonaws.com/doc/2011-08-01/">
<ItemAttributes />
</ItemLookupResponse>
<ecs:ItemLookupResponse xmlns:ecs="http://ecs.amazonaws.com/doc/2011-08-01/">
<ecs:ItemAttributes />
</ecs:ItemLookupResponse>
Теперь перейдем к XPath и пространствам имен.Ваше выражение XPath
//ItemAttributes[contains(ProductGroup, 'Book')]
Одно раздражение в XPath состоит в том, что вы не можете изменить используемое пространство имен без префиксов так же, как и в XML. Таким образом, имена ItemAttributes
и ProductGroup
в приведенном выше списке всегда находятся в «пустом» пространстве имен. Это выражение XPath ничего не соответствует вашему XML-документу, поскольку в «пустом» пространстве имен нет элементов с локальным именем ItemAttributes
, не говоря уже о элементах с дочерним элементом ProductGroup
, содержащим текст Book
.
Однако в большинстве (если не во всех) API-интерфейсах XPath существуют способы привязки префиксов к пространствам имен. Я хотел показать один из способов сделать это с XPath в .NET. Я связал префикс pfx
(я мог выбрать любой префикс, который я хотел) с URI, который я использовал в моем примере выше. Вы бы использовали другой URI для моего составного примера. Затем вы можете использовать выражение XPath
//pfx:ItemAttributes[contains(pfx:ProductGroup, 'Book')]
чтобы найти соответствующий элемент, потому что есть элемент (ы) с именем ItemAttributes
и пространством имен http://ecs.amazonaws.com/doc/2011-08-01/
, и хотя бы один из них содержит дочерний элемент с именем ProductGroup
в том же пространстве имен и с текстовым содержимым Book
.