consulta XPath e tempo

votos
2

Oi, este é o conteúdo do meu arquivo XML:

<?xml version=1.0 encoding=ISO-8859-1?>
<mainNode>
    <sub time=08:00>
        <status id=2>On</status>
        <status id=3>Off</status>
    </sub>
    <sub time=13:00>
        <status id=4>On</status>
        <status id=7>On</status>
    </sub>
    <sub time=16:00>
        <status id=5>On</status>
        <status id=6>On</status>
        <status id=7>Off</status>
        <status id=8>On</status>
    </sub>
    <sub time=20:00>
        <status id=4>Off</status>
        <status id=7>On</status>
    </sub>
    <sub time=23:59>
        <status id=4>On</status>
        <status id=7>On</status>
    </sub>
</mainNode>

Meu programa obtém a hora atual: se eu conseguir 15,59, I deve recuperar toda a id status da próxima vez sub (16.00):

<sub time=16:00>
        <status id=5>On</status>
        <status id=6>On</status>
        <status id=7>Off</status>
        <status id=8>On</status>
    </sub>

Com uma segunda consulta XPath I deve obter todas as id estado do tempo sub anterior (13,00). Como fazer isso? Sei SQL, mas eu sou muito novo para XPath. Eu aceito urls aos recursos XPath graves também, se houver. Obrigado!

Publicado 24/01/2009 em 13:01
fonte usuário
Em outras línguas...                            


4 respostas

votos
0

Se você gerar o XML, você pode mudar a maneira de armazenar o atributo tempo usando um valor inteiro (carrapatos, por exemplo), então você poderia fazer uma comparação numérica fácil usar algo como

//sub[@time > 1389893892]
Respondeu 24/01/2009 em 13:35
fonte usuário

votos
1

Bem, desde que o tempo é HH: MM algo como o seguinte deve funcionar: (I deve desculpar meu sintaxe desde que eu só estou a brincar sem correr, considere esta pseudo-XPath):

xmlns:fn="http://www.w3.org/2005/02/xpath-functions"

//sub[fn:compare(@time,'12:59') > 0][1]/status

Isso deve selecionar todos os elementos onde o tempo é maior do que 0:59 e, em seguida, selecione o primeiro desses elementos.

Você também pode passar o valor '12: 59' como e parâmetro xternal na avaliação XPath.

Respondeu 24/01/2009 em 13:36
fonte usuário

votos
2

Aqui está a solução feia XPath 1.0: -

sub[number((substring-before(@time, ':')) * 60 + number(substring-after(@time, ':'))) &gt; 959][1]

Nota 959 = 15 * 60 + 59, que eu tenho certeza que você pode fazer em seu código de chamada.

Dê esse nó o nó anterior pode ser acessado como: -

preceding-sibling::sub[1]

No entanto, uma solução de senso pragmático, comum seria para carregar os dados XML em um conjunto de estruturas de dados e usar uma linguagem mais adequada para esta tarefa para olhar os itens acima.

Respondeu 24/01/2009 em 13:54
fonte usuário

votos
2

Aqui estão duas soluções:

I. 1.0 XPath

Este é um par de XPath 1.0 expressões que selecionam os nós necessários:

/*/*
    [translate(@time, ':','') 
    > 
     translate('15:59',':','')
    ][1]

selecciona o primeiro subnó com o tempo mais tarde do que 15:59.

/*/*
    [translate(@time, ':','') 
    < 
     translate('15:59',':','')
    ][last()]

selecciona selecciona o primeiro subnó com o anterior de 15:59 subtempo .

Podemos incluir estes em uma transformação XSLT e verificar que o resultado realmente queria é produzido:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes"/>

    <xsl:template match="/">
      First time after 15:59: 
      <xsl:copy-of select=
       "/*/*
          [translate(@time, ':','') 
         > 
           translate('15:59',':','')
          ][1]
      "/>

      First time before 15:59: 
      <xsl:copy-of select=
       "/*/*
          [translate(@time, ':','') 
         &lt; 
           translate('15:59',':','')
          ][last()]
      "/>
  </xsl:template>
</xsl:stylesheet>

Quando a transformação acima é aplicado sobre o documento XML fornecido originalmente:

<mainNode>
    <sub time="08:00">
        <status id="2">On</status>
        <status id="3">Off</status>
    </sub>
    <sub time="13:00">
        <status id="4">On</status>
        <status id="7">On</status>
    </sub>
    <sub time="16:00">
        <status id="5">On</status>
        <status id="6">On</status>
        <status id="7">Off</status>
        <status id="8">On</status>
    </sub>
    <sub time="20:00">
        <status id="4">Off</status>
        <status id="7">On</status>
    </sub>
    <sub time="23:59">
        <status id="4">On</status>
        <status id="7">On</status>
    </sub>
</mainNode>

o resultado desejado é produzido :

  First time after 15:59: 


<sub time="16:00">
        <status id="5">On</status>
        <status id="6">On</status>
        <status id="7">Off</status>
        <status id="8">On</status>
</sub>

  First time before 15:59: 

 <sub time="13:00">
        <status id="4">On</status>
        <status id="7">On</status>
 </sub>

Observe o seguinte:

  1. O uso da XPath translate()função para se livrar dos dois pontos

  2. A utilização da last()função no segundo expressão

  3. Não há necessidade de converter o tempo para segundos antes da comparação

  4. Quando usado como parte de um documento XML (como uma folha de estilo XSLT, o <operador deve ser escapado .

II. XPath 2.0

Em XPath 2.0 , podemos usar as duas expressões a seguir para produzir selecione os nós desejados:

/*/*[xs:time(concat(@time,':00')) 
    gt 
     xs:time('15:59:00')
    ][1]

selecciona o primeiro subnó com o tempo mais tarde do que 15:59.

/*/*[xs:time(concat(@time,':00')) 
   lt 
     xs:time('15:59:00')
    ][last()]

selecciona selecciona o primeiro subnó com o anterior de 15:59 subtempo .

Podemos incluir estes em uma transformação XSLT 2.0 e verificar que o resultado realmente queria é produzido:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:output omit-xml-declaration="yes"/>

    <xsl:template match="/">
      First time after 15:59: 
      <xsl:copy-of select=
       "/*/*[xs:time(concat(@time,':00')) 
           gt 
             xs:time('15:59:00')
             ][1]
      "/>

      First time before 15:59: 
      <xsl:copy-of select=
       "/*/*[xs:time(concat(@time,':00')) 
           lt 
             xs:time('15:59:00')
          ][last()]
      "/>
    </xsl:template>
</xsl:stylesheet>

Quando a transformação acima é aplicada sobre o documento XML originalmente fornecida (o mesmo que na primeira solução), o mesmo resultado desejado é produzido.

Observe o seguinte:

  1. Em XPath 2,0 xs:timeé um tipo de dados nativa . No entanto, a fim de construir um xs:time()dos valores no documento XML, temos que concat a eles a parte que falta segundos.
  2. Em XPath 2.0 xs:timevalores podem ser comparados com os " operadores comarison de valor atómica " tal como ltou gt.
Respondeu 24/01/2009 em 17:53
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more