Writing an XPath Request to Match Elements Based on Attributes and Content

I have an XML like this:

<topics> <topic id="50"/> <topic id="51"/> <topic id="52"/> </topics> <discussions> <discussion type="foo">talked about T50 as Discussion 1000</discussion> <discussion type="bar">Food is yummy!</discussion> <discussion type="foo">talked about T52 as Discussion 1050</discussion> </discussions> 

Given a specific topic identifier ( $topicID ), I would like to do the following:

  • Create an XPath expression that is true if there is a <discussion> with type="foo" that contains the text T$topicID as Discussion <corresponding-discussion-id> .

  • Come up with an XPath expression that, given that $topicID , will extract the Discussion <corresponding-discussion-id> text Discussion <corresponding-discussion-id> .

Is it possible?


Update:

For the first, I think I need something like:

 exists( //discussions/discussion[ @type="foo" and contains(text(), concat($topicId, ??? )) <-- What goes here? I think we need ] some kind of matches(...) around the ) concat(), too. 
+4
source share
2 answers

The following XPath will select the discussion attribute type = "foo" and containing the text "T50 as Discussion" (at $ topicid = 50).

 //discussions/discusson[@type='foo' and contains(., concat('T', $topicid, ' as Discussion ')] 

For a particular discussion item, the corresponding identifier is defined as follows:

 substring-after(normalize-space(.),' as Discussion ') 

We can combine 2 by replacing ".". in the second expression with all the first expression. Please note that if several discussions coincide with the internal expression, we will concatenate their values ​​from the second.

 substring-after(normalize-space( //discussions/discusson[@type='foo' and contains(., concat('T', $topicid, ' as Discussion ')] ),' as Discussion ') 

If there have been several overlapping discussions, you can process them as follows:

 <xsl:for-each select="//topics/topic"> <xsl:variable name="topicid" select="@id" /> <xsl:for-each select="//discussions/discusson[@type='foo' and contains(., concat('T', $topicid, ' as Discussion ')]"> <xsl:variable name="relatedid" select="substring-after(normalize-space(.),' as Discussion ')" /> <!-- do something with $topicid and $relatedid --> </xsl:for-each> </xsl:for-each> 

Function Links:

Personally, I can’t imagine how XSLT is seriously developing without the book by Michael Kay.

+5
source

The discussion of type=foo contains the corresponding topicID :

 /discussions/discussion[@type=foo AND contains(.,'T52')] 
+1
source

Source: https://habr.com/ru/post/1301758/


All Articles