2015-11-04 4 views
1

Я не нашел решение в подобной теме, поэтому я надеюсь, что кто-то может мне помочь. У меня есть XML следующим образом (выдержка):XPath concat все совпадения родственных узлов

<root> 
<identificationInfo> 
<MD_DataIdentification> 
<descriptiveKeywords> 
      <MD_Keywords> 
       <keyword> 
        <gco:CharacterString>Atmospheric conditions</gco:CharacterString> 
       </keyword> 
       <type> 
        <MD_KeywordTypeCode codeListValue="theme"/> 
       </type> 
      </MD_Keywords> 
     </descriptiveKeywords> 
     <descriptiveKeywords> 
      <MD_Keywords> 
       <keyword> 
        <gco:CharacterString>Agriculture</gco:CharacterString> 
       </keyword> 
       <keyword> 
        <gco:CharacterString>Biodiversity</gco:CharacterString> 
       </keyword> 
       <type> 
        <MD_KeywordTypeCode codeListValue="socialBenefitArea"/> 
       </type> 
      </MD_Keywords> 
     </descriptiveKeywords> 

То, что я хочу, чтобы сцепить строки типа и ключевого слова, так что я получить список, который выглядит следующим образом:

theme:Atmospheric conditions 
socialBenefitArea:Agriculture 
socialBenefitArea:Biodiversity 

Я попробовал следующие решения (XPath 1.0 или XPath 2.0 оба могут быть использованы), но всегда возвращается только первая тема «Атмосферные условия» первого совпадения.

  • for $n in /*/gmd:identificationInfo/*/gmd:descriptiveKeywords/gmd:MD_Keywords return string-join(($n/gmd:type/*/@codeListValue, ':', $n/gmd:keyword/*/text()), '')
  • /*/gmd:identificationInfo/*/gmd:descriptiveKeywords/gmd:MD_Keywords/gmd:keyword/concat(*/text(), ':', ../gmd:type/*/@codeListValue)
  • //gmd:descriptiveKeywords/*/string-join((gmd:type/*/@codeListValue, gmd:keyword/*/text()[1]), ':')
  • //gmd:descriptiveKeywords/*/gmd:keyword/concat(following-sibling::gmd:type/*/@codeListValue, ':', ./*/text())

Если XPaths выглядеть правильно, я делаю это в Java с Saxon-HE 9.x.

Что я выяснил, так это то, что оценка возвращает String, а не NODESET, и мне, вероятно, нужно иметь несколько результатов. Какой XPath вернет NODESET?

Благодарим за помощь!

ответ

0

Выражение XPath 2.0 //gco:CharacterString/concat(ancestor::MD_Keywords/type/MD_KeywordTypeCode/@codeListValue, ':', .) возвращается (http://xsltransform.net/6r5Gh2U) последовательность из трех строк

theme:Atmospheric conditions 
socialBenefitArea:Agriculture 
socialBenefitArea:Biodiversity 

Я не понимаю, почему вы просите узла, установленного в XPath 2.0 не устанавливает возвращает узел, а, скорее последовательности узлов или примитивных значений. Поскольку ваш результат не содержится в узлах, но вы хотите конкатенировать строки, содержащиеся в разных узлах, я не вижу, каким образом помогут узлы, выбранные во входе, если вы хотите создавать новые узлы, тогда вам нужны XSLT или XQuery.

0

Я подозреваю, что путаница в отношении строк и наборов узлов возникает из-за того, что вы используете API JAXP, который был разработан для XPath 1.0 и не позволяет использовать полную гибкость XPath 2.0. Если вы хотите вернуть последовательность строк из выражений XPath, как предлагает @Martin Honnen, тогда вам нужно будет использовать API s9api: это обрабатывает полную модель данных XPath 2.0. Вы не можете обойти это ограничение, используя JAXP и результаты набора узлов, поскольку XPath не позволяет создавать новые узлы (только для выбора существующих узлов), а строки, которые вы хотите, не соответствуют существующим узлам.

Однако, если вы действительно ограничены JAXP, то вы можете изменить запрос, чтобы объединить результаты в одну строку, используя функцию string-join() с некоторым подходящим разделителем (например, новой строки) и разделить его на несколько результатов путем токенизации в вызывающем Java-коде.

0

Просто используйте:

/*/*/*/*/MD_Keywords/keyword/*/concat(../../type/*/@codeListValue, ': ', .) 

Какой XPath возвратит NodeSet?

Xpath 3.0 может генерировать узел (-set) с использованием стандартной функции, такой какparse-xml() или parse-xml-fragment()