XQuery Simple Recursive Query дъщерен към горен родител в XML

Въведете xml

<req>
  <family>
    <person>
      <id>id1</id>
      <name>name1</name>
      <mother>mother1</mother>
      <age>age1</age>
    </person>
    <person>
      <id>id2</id>
      <name>name2</name>
      <mother>mother2</mother>
      <age>age2</age>
    </person>
    <person>
      <id>id4</id>
      <name>mother3</name>
      <mother>mother4</mother>
    </person>
    <person>
      <id>id3</id>
      <name>mother2</name>
      <mother>mother3</mother>
      <age>age3</age>
    </person>
  </family>
</req>

Бихте ли ми помогнали как да получа най-горния родител „person“ със съществуващ елемент „age“ за всеки „req/family/person“?

Моят следващ xquery

declare function local:recons($family as element(*), $person as element(*))
    as element(*) {
    let $parrent := for $p in $family/person
    where $p/name=$person/mother
    return local:recons($family,$p)
    return
    <person>
    {$person/*}
    <parrent>{$parrent}</parrent>
    </person>
};

declare function xf:MyTest($inputXML as element(*))
    as element(*) {
       <res>
       <family>
       {
       for $person in $inputXML/family/person
       return local:recons($inputXML/family,$person)
       }
       </family>
       </res>
};

declare variable $inputXML as element(*) external;

xf:MyTest($inputXML)

Очакван резултат

<res>
  <family>
    ...
    <person>
      <id>id2</id>
      <name>name2</name>
      <mother>mother2</mother>
      <age>age2</age>
      <parrent>
        <person>
          <id>id3</id>
          <name>mother2</name>
          <mother>mother3</mother>
          <age>age3</age>
          <parrent/>
        </person>
      </parrent>
    </person>
    ...
  </family>
</res>

Реален резултат

<res>
  <family>
    ...
    <person>
      <id>id2</id>
      <name>name2</name>
      <mother>mother2</mother>
      <age>age2</age>
      <parrent>
        <person>
          <id>id3</id>
          <name>mother2</name>
          <mother>mother3</mother>
          <age>age3</age>
          <parrent>
            <person>
              <id>id4</id>
              <name>mother3</name>
              <mother>mother4</mother>
              <parrent/>
            </person>
          </parrent>
        </person>
      </parrent>
    </person>
    ...
  </family>
</res>

Опитах да използвам предшественик и xpath като '$parrent//person[fn:exists(age)]', неуспешно. Опитах да използвам предшественик и xpath като '$parrent//person[fn:exists(age)]', неуспешно.


person damir    schedule 07.04.2019    source източник
comment
Не съм сигурен, че съм схванал проблема за това къде age е уместен и не сте посочили пълния резултат. Резултатът на xqueryfiddle.liberty-development.net/pPgCcox/3 представлява ли един ти искаш? Подходът за внедряване, който използвах там, е малко по-различен, тъй като рекурсивната функция просто връща съществуващия елемент от входа, вместо да създава нови, но тъй като искате само последния резултат в рекурсивното извикване, мисля, че е по-лесно да направите сравнение на резултат по-късно.   -  person Martin Honnen    schedule 08.04.2019
comment
Мадс, благодаря ти за обратната връзка. Опитах се да направя този предикат, това решение помага добре да се намерят всички родители със съществуваща „възраст“ за човек. Но искам да намеря горен/последен родител със съществуваща „възраст“ за човек. Очакван резултат res/family/person | top(last) само родител Действителен резултат res/family/person | първи родител | втори родител ... | горен (последен) родител   -  person damir    schedule 08.04.2019


Отговори (1)


Коригирайте клаузата where във вашия local:recons(), за да се уверите, че избирате само $parrent (не трябва ли този елемент и променливата да се изписват като родител?), ако има age и name съответства на $person/mother

Можете да направите това лесно с предикатен филтър:

where $p[age]/name = $person/mother    

Приложено към функцията:

declare function local:recons($family as element(*), $person as element(*))
    as element(*) {
    let $parrent := for $p in $family/person
      where $p[age]/name = $person/mother
      return local:recons($family,$p)
    return
      <person>
        {$person/*}
        <parrent>{$parrent}</parrent>
      </person>
};
person Mads Hansen    schedule 08.04.2019