Cieszę się, że to pytanie ma kilka lat, ale przyszedłem tutaj z podobnym problemem i wierzę, że znalazłem odpowiedź.
with x as (select
'<catalog catalog-id="manufacturer-catalog-id">
<category-assignment category-id="category1" product-id="product1"/>
<category-assignment category-id="category1" product-id="product2"/>
<category-assignment category-id="category2" product-id="product3"/>
</catalog>'::xml as t
)
(
select
xpath('/catalog/@catalog-id', cat_node) catalog_id,
xpath('/category-assignment/@category-id', cat_assn_list) category_id,
xpath('/category-assignment/@product-id', cat_assn_list) product_id
from (select unnest(xpath('/catalog/category-assignment', t)) cat_assn_list, t cat_node from x) q
);
Daje to
catalog_id | category_id | product_id
---------------------------+-------------+------------
{manufacturer-catalog-id} | {category1} | {product1}
{manufacturer-catalog-id} | {category1} | {product2}
{manufacturer-catalog-id} | {category2} | {product3}
(3 rows)
To zasadniczo wykonuje wybór podstawowy, który zwraca dwie kolumny 1) xpath, aby uzyskać listę przypisania (wiele wierszy) i 2) oryginalny węzeł kategorii. Zwrócone wiersze są następnie przetwarzane przez instrukcje xpath wyższego poziomu — identyfikator kategorii z kolumny węzła pełnej kategorii i xpath na poziomie kolumny do elementu listy przypisania.
Uważam, że problem OP polegał na tym, że kierowanie tego wyłącznie poza kolumnę listy pojedynczego przypisania oznacza, że ponieważ postgres zwraca zestawy węzłów xml na odpowiednim poziomie, a nie wskaźniki do pojedynczego obiektu, wynik xml zwrócony przez to jest poniżej poziomu katalogu i że xml ndoeset nie może zostać przeniesiony w górę, np. z "przodkiem::".
Mam nadzieję, że to pomoże komuś innemu.
Edytuj — nie mogę komentować wydajności tego, ponieważ uważam, że xpath o identyfikatorze katalogu zostanie powtórzony dla każdego wiersza przypisania w tym samym węźle katalogu.