Skip to content

Commit

Permalink
feat: Parse XPath (#6470)
Browse files Browse the repository at this point in the history
Required by #5247 

Simple XPath parser for tXml utils. Not used for now, but needed for MPD
Patch support.
  • Loading branch information
tykus160 committed Apr 24, 2024
1 parent c9b61fe commit 0883c32
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 0 deletions.
2 changes: 2 additions & 0 deletions externs/shaka/player.js
Expand Up @@ -881,6 +881,8 @@ shaka.extern.InitDataTransform;
* The child nodes or string body of the element
* @property {?shaka.extern.xml.Node} parent
* The parent of the current element
*
* @exportDoc
*/
shaka.extern.xml.Node;

Expand Down
37 changes: 37 additions & 0 deletions lib/util/tXml.js
Expand Up @@ -735,6 +735,34 @@ shaka.util.TXml = class {
}


/**
* Parse xPath strings for segments and id targets.
* @param {string} exprString
* @return {!Array<!shaka.util.TXml.PathNode>}
*/
static parseXpath(exprString) {
const returnPaths = [];
// Split string by paths but ignore '/' in quotes
const paths = exprString
.split(/\/+(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/);
for (const path of paths) {
const nodeName = path.match(/\b([A-Z])\w+/);

// We only want the id attribute in which case
// /'(.*?)'/ will suffice to get it.
const idAttr = path.match(/(@id='(.*?)')/);
if (nodeName) {
returnPaths.push({
name: nodeName[0],
id: idAttr ?
idAttr[0].match(/'(.*?)'/)[0].replaceAll('\'', '') : null,
});
}
}
return returnPaths;
}


/**
* Converts a tXml node to DOM element.
* @param {shaka.extern.xml.Node} node
Expand Down Expand Up @@ -775,3 +803,12 @@ shaka.util.TXml = class {
};

shaka.util.TXml.knownNameSpaces_ = new Map([]);


/**
* @typedef {{
* name: string,
* id: ?string
* }}
*/
shaka.util.TXml.PathNode;
21 changes: 21 additions & 0 deletions test/util/tXml_unit.js
Expand Up @@ -416,4 +416,25 @@ describe('tXml', () => {
expect(TXml.parseFloat(HUGE_NUMBER_STRING)).toBe(Infinity);
expect(TXml.parseFloat('-' + HUGE_NUMBER_STRING)).toBe(-Infinity);
});

it('parseXpath', () => {
expect(TXml.parseXpath('/MPD')).toEqual([{name: 'MPD', id: null}]);
expect(TXml.parseXpath('/MPD/@type'))
.toEqual([{name: 'MPD', id: null}]);

const timelinePath = '/' + [
'MPD',
'Period[@id=\'6469\']',
'AdaptationSet[@id=\'7\']',
'SegmentTemplate',
'SegmentTimeline',
].join('/');
expect(TXml.parseXpath(timelinePath)).toEqual([
{name: 'MPD', id: null},
{name: 'Period', id: '6469'},
{name: 'AdaptationSet', id: '7'},
{name: 'SegmentTemplate', id: null},
{name: 'SegmentTimeline', id: null},
]);
});
});

0 comments on commit 0883c32

Please sign in to comment.