xpath icon indicating copy to clipboard operation
xpath copied to clipboard

Implementing `current()`

Open Hipska opened this issue 2 years ago β€’ 28 comments

I'm wondering why the current() function hasn't been implemented, and if it would make much time to do so.

I'm currently in the situation where I would need a query like //cd[@title=current()/@ref]. The node navigator used for the expression evaluate isn't the document root, but a previously selected node.

Hipska avatar Apr 13 '22 20:04 Hipska

@zhengchun?

Hipska avatar Apr 25 '22 14:04 Hipska

current() is only supported by XSLT. You can try this //cd[@title=@ref]

zhengchun avatar Apr 27 '22 07:04 zhengchun

Doesn't that only select cd nodes of which title attribute equals their ref attribute?

Edit: wow that actually worked.. Thanks man!

Hipska avatar Apr 27 '22 07:04 Hipska

Scrap that, it seems it didn't work, it always picks the first one in this case: ../../measType[@p=@p] (as I would expect)

Hipska avatar May 03 '22 18:05 Hipska

Hello, Need a sample document to test.

or try this ../../measType[@p]

zhengchun avatar May 04 '22 05:05 zhengchun

That gives the same result. Its strange, as I was really under the impression your solution first worked..

Anyway, this is a simplified version of the file:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="MeasDataCollection.xsl"?>
<measCollecFile xmlns="http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec">
	<measData>
		<managedElement localDn="foobar.example.com" />
		<measInfo measInfoId="metric_name">
			<measType p="1">field1</measType>
			<measType p="2">field2</measType>
			<measValue measObjLdn="identifier">
				<r p="1">31854</r>
				<r p="2">159773</r>
			</measValue>
		</measInfo>
		<measInfo measInfoId="metric_name2">
			<measType p="1">field3</measType>
			<measType p="2">field4</measType>
			<measValue measObjLdn="identifier">
				<r p="1">1234</r>
				<r p="2">567</r>
			</measValue>
		</measInfo>
	</measData>
</measCollecFile>

And the selected node is each time r, so I need an xpath to find out the field name of it.

Hipska avatar May 04 '22 07:05 Hipska

like this //r[@p]/ancestor::measInfo/measType[@p]

//r[@p]/../../measType[@p]

zhengchun avatar May 04 '22 07:05 zhengchun

That's even worse, now all metrics have field name field1.

The Path is run on each r node. So I think only ../../measType[@p=current()/@p] would work..

Hipska avatar May 04 '22 08:05 Hipska

using the nested query to solve. like this

for _,n:=range xmlquery.Find(doc,"//r[@p]")
{
    for _,nn:=range xmlquery.Find(n,`../../measType[@p='`+n.SelectAttr("p")+`']`){}
}

zhengchun avatar May 04 '22 12:05 zhengchun

Well, yeah. I can't change the code. I'm using telegraf: https://github.com/influxdata/telegraf/blob/6dc2b99549b3fc4684295ebcd2975cee96a1fa28/plugins/parsers/xpath/parser.go#L419-L447

Hipska avatar May 04 '22 13:05 Hipska

I tested //r[@p=../../measType/@p] and it only return the first one node(expected matched 4 node but only gave 2), this is a bug.

zhengchun avatar May 04 '22 15:05 zhengchun

Indeed, see GO playground vs XPather. Can I help with trying to fix it?

Edit: And what should be the correct path be after the fix? ../../measType[@p] or ../../measType[@p=@p]?

Hipska avatar May 05 '22 12:05 Hipska

//r[@p=../../measType/@p] should be your expression to sove your problem.

zhengchun avatar May 05 '22 15:05 zhengchun

No, I have an r and need an xpath to find it’s measType.

Your xpath selects every r that has a corresponding measType.

Hipska avatar May 05 '22 18:05 Hipska

@zhengchun any update on this? Can I help to fix this?

Hipska avatar May 12 '22 08:05 Hipska

@Hipska , You can try to fix this and submit PR.

zhengchun avatar May 12 '22 12:05 zhengchun

I would love to fix it, but I don't see where the bug is.

Hipska avatar May 12 '22 14:05 Hipska

Sorry,I no idea how to implement Current() now, It's a XSLT function.

zhengchun avatar May 21 '22 05:05 zhengchun

Oh, but it seems you fixed it?

Hipska avatar May 21 '22 20:05 Hipska

I just fixed this expression a[@b=../@b], fixed bug with parent query on current node in the filter query.

zhengchun avatar May 22 '22 02:05 zhengchun

Hmm, then this playground should return 4 nodes, right? https://go.dev/play/p/qeMkl0NqoOT

Edit: nevermind, there is no release yet πŸ™‚ https://go.dev/play/p/sI48ALhbizY πŸ‘

Hipska avatar May 23 '22 10:05 Hipska

I just tested latest version of telegraf (which includes the latest version of this library), but my use-case seems still not to be solved. I'm also not sure what the correct xpath for my problem should be.

Edit: See the following https://go.dev/play/p/ozvF3CfdDXT I would expect this to be the output of that:

#0 <r p="1">31854</r>
	<measType p="1">field1</measType>
#1 <r p="2">159773</r>
	<measType p="2">field2</measType>
#2 <r p="1">1234</r>
	<measType p="1">field3</measType>
#3 <r p="2">567</r>
	<measType p="2">field4</measType>

Program exited.

Do You agree? If not, what should my second xpath query be to achieve this wanted result?

Hipska avatar Jun 14 '22 08:06 Hipska

@Hipska , The actually result from your go code execute is correct, your expect result is not right.

	for i, n := range xmlquery.Find(doc, "//r[@p=../../measType/@p]") {
		fmt.Printf("#%d %s\n", i, n.OutputXML(true))
		for _, nn := range xmlquery.Find(n, `../../measType[@p=./@p]`) {  -- Here
			fmt.Printf("\t%s\n", nn.OutputXML(true))
		}
	}

xmlquery.Find(n, ../../measType[@p=./@p]), HERE, you tell xpath to start search from the specified node n, xpath will according on your ../../measType[@p=./@p] to matching. and @p=./@p just telling xpath target node have @p attribute, not your expect `@p=n[@p]'.

You should change your query from xmlquery.Find(n, "../../measType[@p=./@p]") to xmlquery.Find(n, "../../measType[@p=β€œ+ n.Attr("p") +”]β€œ)

You can try take your xpath expression execute on the another program language and see the result.

zhengchun avatar Jun 15 '22 03:06 zhengchun

@zhengchun sorry for this late response. the code itself cannot be changed as this is what telegraf is doing. So I am looking for the correct xpath query to achieve my wanted result..

Hipska avatar Aug 02 '22 15:08 Hipska

So, what is your expected xpath if we can implement the current() function.

In the above example, if you can nested for...loop why you can't change xpath expression to replace ../../measType[@p=./@p] with ../../measType[@p=β€œ+ n.Attr("p") +”]?

You can provide an example and what is you expected result.

zhengchun avatar Aug 05 '22 06:08 zhengchun

Hi, sorry to be so late on this..

In the telegraf config, I'm only able to pass a string, see earlier shared code. So I need a single string/xpath that returns the expected measType node. ../../measType[@p=β€œ+ n.Attr("p") +”] is not possible and will not work.

Hipska avatar Feb 14 '23 08:02 Hipska

I find a solution that saving the query node 'n' as a local variable used by current() function in the query context, like this jsonquery.Find(n,"../../measType[@p=current()/@p]")

zhengchun avatar Feb 20 '23 10:02 zhengchun

Yeah, the whole reason of this issue is because of the current() function is not implemented:

panic: not yet support this function current()

Hipska avatar Feb 20 '23 10:02 Hipska