Pergunta

Dado o seguinte XML:

<current>
  <login_name>jd</login_name>
</current>
<people>
  <person>
    <first>John</first>
    <last>Doe</last>
    <login_name>jd</login_name>
  </preson>
  <person>
    <first>Pierre</first>
    <last>Spring</last>
    <login_name>ps</login_name>
  </preson>
</people>

Como posso obter "John Doe" no matcher atual/de login?

Eu tentei o seguinte:

<xsl:template match="current/login_name">
  <xsl:value-of select="../people/first[login_name = .]"/>
  <xsl:text> </xsl:text>
  <xsl:value-of select="../people/last[login_name = .]"/>
</xsl:template>
Foi útil?

Solução

Eu definiria uma chave para indexar as pessoas:

<xsl:key name="people" match="person" use="login_name" />

Usar uma chave aqui simplesmente mantém o código limpo, mas você também pode achar útil para eficiência se precisar recuperar o código com frequência. <person> elementos baseados em seus <login_name> criança.

Eu teria um modelo que retornasse o nome formatado de um determinado <person>:

<xsl:template match="person" mode="name">
  <xsl:value-of select="concat(first, ' ', last)" />
</xsl:template>

E então eu faria:

<xsl:template match="current/login_name">
  <xsl:apply-templates select="key('people', .)" mode="name" />
</xsl:template>

Outras dicas

Você quer current() função

<xsl:template match="current/login_name">
  <xsl:value-of select="../../people/person[login_name = current()]/first"/>
  <xsl:text> </xsl:text>
  <xsl:value-of select="../../people/person[login_name = current()]/last"/>
</xsl:template>

ou um pouco mais limpo:

<xsl:template match="current/login_name">
  <xsl:for-each select="../../people/person[login_name = current()]">
    <xsl:value-of select="first"/>
    <xsl:text> </xsl:text>
    <xsl:value-of select="last"/>
  </xsl:for-each>
</xsl:template>

Se você precisar acessar vários usuários, então JeniT's <xsl:key /> abordagem é ideal.

Aqui está minha alternativa:

<xsl:template match="current/login_name">
    <xsl:variable name="person" select="//people/person[login_name = .]" />
    <xsl:value-of select="concat($person/first, ' ', $person/last)" />
</xsl:template>

Atribuímos o selecionado <person> nó para uma variável, então usamos o concat() função para gerar os nomes/sobrenomes.

Também há um erro no seu XML de exemplo.O <person> nó termina incorretamente com </preson> (erro de digitação)

Uma solução melhor poderia ser dada se soubéssemos a estrutura geral do documento XML (com nós raiz, etc.)

Acho que o que ele realmente queria era a substituição do nó "atual" na correspondência, e não uma correspondência no nó pessoal:

<xsl:variable name="login" select="//current/login_name/text()"/>

<xsl:template match="current/login_name">
<xsl:value-of select='concat(../../people/person[login_name=$login]/first," ", ../../people/person[login_name=$login]/last)'/>

</xsl:template>

Apenas para adicionar meus pensamentos à pilha

<xsl:template match="login_name[parent::current]">
 <xsl:variable name="login" select="text()"/>
 <xsl:value-of select='concat(ancestor::people/child::person[login_name=$login]/child::first/text()," ",ancestor::people/child::person[login_name=$login]/child::last/text())'/>
</xsl:template>

Eu sempre prefiro usar os eixos explicitamente em meu XPath, IMHO mais detalhado, mas mais claro.

Dependendo da aparência do restante dos documentos XML (supondo que seja apenas um fragmento), talvez seja necessário restringir a referência a "ancestor::people", por exemplo, usando "ancestor::people[1]" para restringir às primeiras pessoas antepassado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top