Как получить узел с минимальным значением атрибута?

Моя структура xml выглядит примерно так:

<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>

я хочу выбрать узел блока, который имеет минимальное значение "l", т.е. "688"

Я знаю, что в XPath 2.0 есть функция min(), но я использую Xpath1.0.

я пробовал это

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

Как я могу использовать XPath для поиска минимального значения атрибута в наборе элементов?

Но это дает мне несколько нодлистов. если это min, это должен быть только один узел. Любое другое возможное и эффективное решение этого ?? Пожалуйста, предложите. Спасибо


person Maverick    schedule 11.06.2015    source источник
comment
Пожалуйста, опубликуйте хорошо сформированный образец XML, который люди могут использовать для проверки своего xpath. Ваш xpath также не совсем соответствует образцу XML (в xpath есть par, line и т. д., но ни один из этих элементов не показан в XML): stackoverflow.com/help/mcve   -  person har07    schedule 11.06.2015
comment
Я отредактировал ваш образец XML, чтобы сделать его правильно сформированным, не стесняйтесь настраивать его дальше, если считаете необходимым продемонстрировать проблему (просто держите его в правильном формате).   -  person har07    schedule 11.06.2015


Ответы (3)


ОБНОВЛЕНИЕ 2:

Согласно обновленному образцу XML, предполагая, что вы хотите найти минимальное значение атрибута l элемента line, попробуйте следующим образом:

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

вывод:

Attribute='l="253"'

ОБНОВЛЕНИЕ:

На самом деле, имея комбинацию preceding-sibling::block/@l <= @l и following-sibling::block/@l < @l, у вас все равно нет шансов получить дубликат. xpath возвращает только первое минимальное значение в случае существования повторяющихся значений из-за <=. Настоящая проблема, которую я обнаружил в вашем xpath, заключается в том, что вы используете > в оценке following-sibling вместо использования <.

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

Но это дает мне несколько нодлистов. если это min, это должен быть только один узел.

Если единственная загвоздка в том, что ваш xpath может возвращать несколько значений, вы можете просто обернуть весь xpath с помощью ()[1], чтобы ограничить результат одним значением, например (отформатировано для удобочитаемости):

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

вывод в xpath tester:

Attribute='l="688"'
person har07    schedule 11.06.2015
comment
Это хорошо работает с образцом xml, который я опубликовал, но xml, с которым я работаю, имеет аналогичную структуру, но довольно большой размер. Когда я выполняю это выражение с моим xml, оно всегда дает мне первый элемент/узел. - person Maverick; 11.06.2015
comment
Еще раз: stackoverflow.com/help/mcve. Попробуйте проверить, какие элементы дублируются в выводе, когда вы запускаете этот xpath против вашего фактического XML. Затем попробуйте взять только эту часть (повторяющиеся элементы) и минимальные элементы вокруг них, просто чтобы воспроизвести проблему, а затем опубликуйте сокращенный XML в своем вопросе. Трудно сказать, не имея возможности воспроизвести вашу проблему - person har07; 11.06.2015
comment
Собственно, я отменил свое предложение использовать ()[1]. Так как насчет xpath в верхней части моего ответа? Если это тоже не сработало, см. мой предыдущий комментарий - person har07; 11.06.2015
comment
@AnkitNayak проверь мое обновление. Обратите внимание: вы должны были опубликовать XML в вопросе, а не в ответе. Кроме того, он снова плохо сформирован!! - person har07; 13.06.2015
comment
Вы пробовали это на XPath Tester, он дает No Match. пытаюсь разобраться ;-( - person Maverick; 13.06.2015
comment
уверен, что вывод, который я получаю от тестера xpath, входной xml был xml, который вы разместили в ответе после замены всех -< на < - person har07; 13.06.2015
comment
спасибо, это работает, как насчет добавления еще одного условия в выражение. Это должно было вернуть элемент с минимальным значением l. Теперь у меня есть выражение //page/block/text/par/line[@b ‹ 297 или @b - 229 ‹ 30], которое возвращает мне несколько элементов, и мне нужен элемент с min l среди них. Я имею в виду, как мне объединить эти два выражения. - person Maverick; 14.06.2015

Вот Xml, который я использую. Приведенный выше xpath всегда возвращает первый элемент.

строка 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>
person Maverick    schedule 11.06.2015

Используйте приведенный ниже код и уже известное решение для xpath 1.0, см. ссылку здесь Как я могу использовать XPath для поиска минимального значения атрибута в наборе элементов?

/page/block[not(preceding-sibling::block/@l &lt;= @l) and not(following-sibling::block/@l &lt; @l)]/@l
person mkanugan    schedule 13.06.2015