XPath separate key and value of group

Using XPath 3.1 (for instance, inside the browser with Saxon-JS (https://www.saxonica.com/saxon-js/documentation2/index.html), also with Node) you can use a path expression that creates an XPath 3.1 XDM map with the key and value:

//dd[@class = 'product-specifications-v2__items']/p[@class = 'product-specifications-v2__key']!map { 'key' : normalize-space(), 'value' : following-sibling::div[@class = 'product-specifications-v2__value'][1]!normalize-space() }

const html = `<dd class="product-specifications-v2__items">
  <p class="product-specifications-v2__key">
    EAN/UPC - product
  </p>
  <div class="product-specifications-v2__value">
    <p class="product-specifications-v2__value-item">
      7912372 
    </p>
  </div>
  <p class="product-specifications-v2__key">
    Weight
  </p>
  <div class="product-specifications-v2__value">
    <p class="product-specifications-v2__value-item">
      2,170
      <span>kg</span>
    </p>
  </div>
</dd>`;

var htmlDoc = new DOMParser().parseFromString(html, 'text/html');

const results = SaxonJS.XPath.evaluate(`//dd[@class = 'product-specifications-v2__items']/p[@class = 'product-specifications-v2__key']!map { 'key' : normalize-space(), 'value' : following-sibling::div[@class = 'product-specifications-v2__value'][1]!normalize-space() }`, htmlDoc, { 'xpathDefaultNamespace' : 'http://www.w3.org/1999/xhtml' });

console.log(results);
<script src="https://www.saxonica.com/saxon-js/documentation2/SaxonJS/SaxonJS2.rt.js"></script>

The JavaScript API of Saxon-JS returns the sequence of XDM maps as an array of JSON objects to JavaScript.