有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java xpath第一个可用值

我正在开发一个软件,在注册表(用户列表)上执行CRUD操作。没有打算使用DBMS,但是使用了大量带有Simple XML framework的XML

从整个列表中选择一部分用户,并由一个包含memento模式的java组件进行缓冲。这是为了保存状态和所选用户,以便能够从软件被终止的位置继续

我希望尽可能地精简xml memento文件,以便为每个用户创建一个唯一的索引,以避免为选定的用户写入所有数据

用户列表如下所示:

<users>
    <user id="1">
        <name> ... </name>
        <role> ... </role>
    </user>
    <user id="2">
        <name> ... </name>
        <role> ... </role>
    </user>
    ...
</users>

而纪念品文件是这样的:

<us>
    <u>1</u>
    ...
    <u>7</u>
</us>

现在。我还希望尽可能少地使用删除用户释放的索引来保持碎片。换句话说,如果我使用这个索引:

1    2    3    4

我添加了一个索引为5的用户

1    2    3    4    5

我删除了用户3

1    2         4    5

现在我想添加另一个用户,我希望分配的索引将是第一个可用的索引,在本例中为3,因此

1    2    3    4    5

请注意,可能有多个索引丢失,因此我不考虑使用变量或数据结构来保存被释放的值的历史,以便可以回收它们。我认为当我需要一个新的索引时,计算第一个可用的索引会更有效

最后,问题来了:有没有一种方法可以使用xPath获得缺少下一个值的第一个索引(抱歉,我找不到合适的词来描述这种值)

如果没有任何索引缺失,该表达式将收敛到其中的max(),否则它将返回缺失索引之前的值

当我想起忘记的细节时,我会更新这个问题。 致以最良好的祝愿


共 (1) 个答案

  1. # 1 楼答案

    使用XPath 1.0表达式

     count(/*[not(u[not(text())])]/u) 
    +
     count(/*/u[not(text())][1]/preceding-sibling::u)
    + 1
    

    这可以缩写为(可读性较差):

    count(
            /*[not(u[not(text())])]/u
          |
            /*/u[not(text())][1]/preceding-sibling::u
         )
    + 1
    

    验证

    使用以下XSLT 1.0转换,只计算表达式并输出结果:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>
    
      <xsl:template match="node()|@*">
        <xsl:value-of select=
        "count(/*[not(u[not(text())])]/u) 
        +
         count(/*/u[not(text())][1]/preceding-sibling::u)
         + 1"
        />
      </xsl:template>
    </xsl:stylesheet>
    

    使用不同的“memento”XML文档,例如:

    首先

    <us>
        <u>1</u>
        <u>2</u>
        <u>3</u>
        <u>4</u>
        <u>5</u>
        <u>6</u>
        <u>7</u>
    </us>
    

    结果:8

    秒:

    <us>
        <u></u>
        <u>2</u>
        <u>3</u>
        <u>4</u>
        <u>5</u>
        <u>6</u>
        <u>7</u>
    </us>
    

    结果:1

    第三

    <us>
        <u>1</u>
        <u>2</u>
        <u>3</u>
        <u>4</u>
        <u>5</u>
        <u>6</u>
        <u></u>
    </us>
    

    结果:7

    第四

    <us>
        <u>1</u>
        <u>2</u>
        <u></u>
        <u>4</u>
        <u>5</u>
        <u>6</u>
        <u>7</u>
    </us>
    

    结果:3

    第五

    <us>
        <u>1</u>
        <u>2</u>
        <u>3</u>
        <u></u>
        <u>5</u>
        <u></u>
        <u>7</u>
    </us>
    

    结果:4

    第六

    <us>
    </us>
    

    结果:1


    解释

    此解决方案中的XPath表达式是三个子表达式的总和:

    a)count(/*[not(u[not(text())])]/u)

    b)count(/*/u[not(text())][1]/preceding-sibling::u)

    c)1

    1. 表达式a)是所有/*/u元素的计数,当它们都有一个文本子元素(在我们的特定情况下,是一个数字)。这里使用了双重否定的定律:对于任何序列项不缺少一个给定的属性P,该序列具有其所有项都具有属性P的属性

    阅读更多关于双重否定法则的信息,这里:http://www.britannica.com/topic/law-of-double-negation和这里:https://en.wikipedia.org/wiki/Double_negation

    在这种情况下,顺序是:

    /*/u

    属性p是:

    u[text()]

    换句话说,所有/*/u元素都有一个子文本节点

    我们只需要把1(expressionc)加到这个序列中的项数上,这就是这个特殊情况的解决方案

    正如我们马上就会看到的,每当表达式a)的计算结果为非零时,表达式b)的计算结果为零,反之亦然

    1. 表达式b)是没有文本子元素的第一个/*/u元素的前一个同级数。同样,在这种特殊情况下,解决方案只是添加1(表达式c)

    为什么两个序列a)b)的项数都不是零

    之所以如此,是因为a)的项数非零,当且仅当其所有项都有一个文本子项时。在本例中,expressionb)不选择u元素,因为它们必须是另一个没有文本子元素的u元素的前辈。然而,没有这样的元素,因为序列a中的所有元素(这些都是/*/u元素)都有一个文本子元素