3

My xml structure is something like this :

<page height="777" width="777">
    <block r="777" l="778" blockType="Text">
        <region/>
        <separator/>
    </block>
    <block r="777" l="790" blockType="Text">
        <region/>
        <separator/>
    </block>
    <block r="777" l="688" blockType="Text">
        <region/>
        <text/>
    </block>
</page>

i want the select the block node which has the min "l" value i.e "688"

I know there is a min() function available in XPath 2.0, but i am using Xpath1.0.

I tried this

     //XPathExpression pattern2TextExpr = 
xPath.compile("//page/block[not(preceding-sibling::block/@l < = @l) and not(following-sibling::block/@l >@l)]/@l");

How can I use XPath to find the minimum value of an attribute in a set of elements?

But this gives me multiple nodelist. if it's min it should be only one node. Any other possible and efficient solution to this ?? Please suggest. Thanks

Community
  • 1
  • 1
Maverick
  • 1,396
  • 5
  • 22
  • 42
  • 1
    Please post well-formed XML sample that people can use to test their xpath. Your xpath also doesn't correspond exactly to the XML sample (the xpath has `par`, `line`, etc, but none of those elements shown in the XML) : http://stackoverflow.com/help/mcve – har07 Jun 11 '15 at 09:57
  • I have edited your XML sample to make it well-formed, feel free to tweak it further if you feel necessary to demonstrates the problem (just keep it well-formed). – har07 Jun 11 '15 at 11:15

3 Answers3

3

UPDATE 2:

According to the updated XML sample, assuming that you want to find minimum value of l attribute of line element, try this way :

//page/block/text/par/line[not(preceding::line/@l <= @l) and not(following::line/@l<@l)]/@l

output :

Attribute='l="253"'

UPDATE :

Actually, by having combination of preceding-sibling::block/@l <= @l and following-sibling::block/@l < @l, there is no chance you get duplicate anyway. The xpath returns only the first minimum value in case of duplicate values exists, because of <=. The real problem I found in your xpath is, that you use > in the following-sibling evaluation instead of using <.

 //page/block[
        not(preceding-sibling::block/@l <= @l) 
            and 
        not(following-sibling::block/@l < @l)
    ]/@l

But this gives me multiple nodelist. if it's min it should be only one node.

If the only catch is that your xpath may return multiple values, then you can simply wrap the entire xpath with ()[1] to limit the result to single value, for example (formatted for readability) :

(
 //page/block[
        not(preceding-sibling::block/@l <= @l) 
            and 
        not(following-sibling::block/@l > @l)
    ]/@l
)[1]

output in xpath tester :

Attribute='l="688"'
har07
  • 88,338
  • 12
  • 84
  • 137
  • This works well with the sample xml which I had posted, but the xml which i am working with is of similar structure ,but quite big in size. When i execute this expression with my xml it always gives me the first element/node. – Maverick Jun 11 '15 at 13:04
  • Once again : http://stackoverflow.com/help/mcve. Try to inspect which elements are duplicated in the output when you run this xpath against your actual XML. Then try to take only that portion (duplicate elements) and minimal elements around them, just to be able to reproduce the problem, then post the reduced XML in your question. It's hard to tell without being able to reproduce your problem – har07 Jun 11 '15 at 13:08
  • Actually, I cancelled my suggestion to use `()[1]`. So how about the xpath at the top of my answer? If that didn't work too, see my previous comment – har07 Jun 11 '15 at 13:10
  • @AnkitNayak check my update. Note, you should've posted the XML in *question*, not answer. Also, it's not well-formed again!! – har07 Jun 13 '15 at 08:01
  • did u try this on XPath Tester, it gives "No Match". I am trying to figure out ;-( – Maverick Jun 13 '15 at 08:11
  • 1
    sure, that the output I get from xpath tester, input xml was the xml you posted in answer after replacing all `-<` with `<` – har07 Jun 13 '15 at 09:33
  • thanks it works, how about adding one more condition to the expression. This was to return the element with min "l" value. Now i have an expression //page/block/text/par/line[@b < 297 or @b - 229 < 30] ,which returns me multiple elements and i want the element with min "l" among those. I mean how do i combine these two expressions. – Maverick Jun 14 '15 at 08:37
0

Here's the Xml which i am using. The above xpath always returns the first element.

line b="240" r="1148" t="208" l="1026"

<page originalCoords="1" resolution="300" height="3641" width="2656">
-<block b="246" r="1154" t="207" l="1020" blockName="" blockType="Text">
-<text>
-<par lineSpacing="890">
-<line b="240" r="1148" t="208" l="1026" baseline="280">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="259" r="1540" t="215" l="1336" blockName="" blockType="Text">
-<text>
-<par lineSpacing="890">
-<line b="252" r="1534" t="217" l="1342" baseline="282">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="303" r="2510" t="235" l="2075" blockName="" blockType="Text">
-<region>
<rect b="236" r="2104" t="235" l="2076"/>
<rect b="237" r="2142" t="236" l="2076"/>
<rect b="238" r="2180" t="237" l="2076"/>
</region>
-<text>
-<par lineSpacing="1000">
-<line b="289" r="2504" t="237" l="2081" baseline="283">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="966" r="1607" t="191" l="232" blockName="" blockType="Text">
-<text>
-<par lineSpacing="890" align="Justified">
-<line b="252" r="790" t="198" l="258" baseline="287">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
-<text>
-<par lineSpacing="1230" align="Justified" leftIndent="900">
-<line b="298" r="841" t="243" l="272" baseline="339">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="984">
-<line b="370" r="1479" t="299" l="255" baseline="394">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
-<line b="424" r="1605" t="343" l="253" baseline="435">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1224" align="Justified" leftIndent="900">
-<line b="467" r="1581" t="395" l="282" baseline="489">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1224" align="Justified" leftIndent="900">
-<line b="521" r="1580" t="446" l="281" baseline="540">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1224" align="Justified" leftIndent="900">
-<line b="565" r="1578" t="497" l="282" baseline="591">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1200" align="Justified" leftIndent="900">
-<line b="618" r="1577" t="546" l="278" baseline="638">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1200" align="Justified" leftIndent="900">
-<line b="667" r="1576" t="596" l="278" baseline="688">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1200" align="Justified" leftIndent="900">
-<line b="718" r="1573" t="644" l="277" baseline="738">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1200" align="Justified" leftIndent="900">
-<line b="758" r="1481" t="695" l="276" baseline="788">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1200" align="Justified" leftIndent="900">
-<line b="818" r="1583" t="744" l="274" baseline="837">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1200" align="Justified" leftIndent="900">
-<line b="870" r="1587" t="794" l="273" baseline="889">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="950" align="Justified" leftIndent="900">
-<line b="916" r="1580" t="842" l="272" baseline="934">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="950" align="Justified" leftIndent="900">
-<line b="960" r="1579" t="892" l="269" baseline="983">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="756" r="1748" t="428" l="1686" blockName="" blockType="Text">
-<text>
-<par lineSpacing="1360" align="Justified">
-<line b="477" r="1748" t="434" l="1694" baseline="499">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1060" align="Justified">
-<line b="516" r="1740" t="484" l="1700" baseline="541">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="950" align="Justified">
-<line b="563" r="1737" t="532" l="1699" baseline="587">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1176" align="Justified">
-<line b="608" r="1738" t="578" l="1697" baseline="632">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
-<line b="666" r="1743" t="627" l="1696" baseline="680">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="950" align="Justified">
-<line b="714" r="1742" t="672" l="1688" baseline="738">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="950" align="Justified">
-<line b="750" r="1732" t="720" l="1694" baseline="774">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="575" r="2129" t="355" l="1797" blockName="" blockType="Text">
-<text>
-<par lineSpacing="1170" leftIndent="1100">
-<line b="405" r="2055" t="362" l="1847" baseline="414">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1200" align="Justified">
-<line b="466" r="2003" t="421" l="1800" baseline="481">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1200" align="Justified">
-<line b="522" r="2120" t="471" l="1802" baseline="534">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1200" align="Right">
-<line b="569" r="2119" t="522" l="1883" baseline="579">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="421" r="2436" t="367" l="2215" blockName="" blockType="Text">
-<text>
-<par lineSpacing="950">
-<line b="415" r="2430" t="373" l="2221" baseline="414">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="585" r="2494" t="496" l="2403" blockName="" blockType="Text">
-<text>
-<par lineSpacing="890">
-<line b="531" r="2488" t="502" l="2412" baseline="535">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="890">
-<line b="579" r="2487" t="552" l="2409" baseline="582">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="766" r="2125" t="563" l="1894" blockName="" blockType="Text">
-<text>
-<par lineSpacing="890" align="Justified">
-<line b="616" r="2117" t="568" l="1904" baseline="624">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1128" align="Justified">
-<line b="676" r="2117" t="625" l="1897" baseline="676">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1128" align="Right">
-<line b="712" r="2117" t="665" l="1980" baseline="725">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
-<line b="760" r="2115" t="718" l="1900" baseline="770">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="776" r="2493" t="591" l="2399" blockName="" blockType="Text">
-<text>
-<par lineSpacing="1120" align="Justified">
-<line b="640" r="2485" t="597" l="2403" baseline="631">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1152" align="Justified">
-<line b="675" r="2484" t="646" l="2408" baseline="677">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1152" align="Justified">
-<line b="722" r="2483" t="693" l="2407" baseline="726">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1152" align="Justified">
-<line b="770" r="2483" t="742" l="2407" baseline="774">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
-<block b="935" r="2336" t="775" l="2185" blockName="" blockType="Text">
-<text>
-<par lineSpacing="1360" align="Justified">
-<line b="838" r="2328" t="780" l="2202" baseline="846">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
-<par lineSpacing="1296" align="Justified">
-<line b="889" r="2326" t="841" l="2199" baseline="886">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
-<line b="935" r="2327" t="877" l="2208" baseline="938">
<formatting lang="EnglishUnitedStates">data scrambled</formatting>
</line>
</par>
</text>
</block>
</page>
Maverick
  • 1,396
  • 5
  • 22
  • 42
0

Please use the below code and already known solution for xpath 1.0, please see the link here How can I use XPath to find the minimum value of an attribute in a set of elements?

/page/block[not(preceding-sibling::block/@l &lt;= @l) and not(following-sibling::block/@l &lt; @l)]/@l
Community
  • 1
  • 1
mkanugan
  • 62
  • 9