Pergunta

Deve haver uma maneira genérica para transformar alguns XML hierárquica tais como:

<element1 A="AValue" B="BValue">
   <element2 C="DValue" D="CValue">
      <element3 E="EValue1" F="FValue1"/>
      <element3 E="EValue2" F="FValue2"/>
   </element2>
   ...
</element1>

no XML achatada (html) pegando atributos selecionados ao longo do caminho e fornecer etiquetas diferentes para os atributos que tornam os cabeçalhos das colunas.

<table>
   <tr>
     <th>A_Label</th>
     <th>D_Label</th>
     <th>E_Label</th>
     <th>F_Label</th>
   </tr>
   <tr>
     <td>AValue</td>
     <td>DValue</td>
     <td>EValue1</td>
     <td>FValue1</td>
   </tr>
   <tr>
     <td>AValue</td>
     <td>DValue</td>
     <td>EValue2</td>
     <td>FValue2</td>
   </tr>
<table>

OK, então não há solução genérica devido ao atributo re-rotulagem, mas você começa o que eu quero dizer, esperançoso. Eu apenas comecei em todo o material do XSLT / XPath então eu vou trabalhar com isso em tempo útil, mas nenhuma pista seria útil.

Foi útil?

Solução

Eu não estou 100% certo do que você está tentando fazer, mas esta solução pode funcionar se o seu element1, element2 e element3 são aninhados de forma consistente.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/">
        <table>
            <xsl:apply-templates select="//element3"></xsl:apply-templates>
        </table>
    </xsl:template>

    <xsl:template match="element3">
        <tr>
            <td><xsl:value-of select="../../@A"/></td>
            <td><xsl:value-of select="../../@B"/></td>
            <td><xsl:value-of select="../@C"/></td>
            <td><xsl:value-of select="../@D"/></td>
            <td><xsl:value-of select="@E"/></td>
            <td><xsl:value-of select="@F"/></td>
        </tr>
        <xsl:apply-templates select="*"></xsl:apply-templates>
    </xsl:template>

</xsl:stylesheet>

Outras dicas

Eu precisava de um XSLT semelhante, mas com profundidade desconhecida, aqui está como eu fiz isso.

Primeiro, adicione um invólucro para a tabela HTML / def lista resultante e chamar o modo de template = "vômito" para achatar a nossa árvore de XML:

<xsl:element name="div">
    <xsl:attribute name="class" select="puke" />
    <xsl:apply-templates select="$notice" mode="puke" />
</xsl:element>  

Aqui nós corresponder cada nó para exibir seu conteúdo (por exemplo text ()) e seus atributos. Fazemos isso de forma recursiva. Eu costumava dl / dt / dd porque minha árvore fonte era uma árvore complexa que não pode ser achatar como um.

<!-- @description: 
    Display all field from the notice so the customer can tell what he want
-->
<xsl:template match="node()" mode="puke">
<xsl:message>
    puking : <xsl:value-of select="local-name( . )" />
</xsl:message>
    <xsl:element name="dl">
        <xsl:element name="dt">
            <xsl:attribute name="class">tagName</xsl:attribute> 
            <xsl:value-of select="local-name( . )" />
        </xsl:element>
        <xsl:element name="dd">
            <xsl:attribute name="class">tagText</xsl:attribute>
            <xsl:value-of select="text()" /></xsl:element> 
        <xsl:element name="dl">
            <xsl:attribute name="class">attr</xsl:attribute>
            <!-- display attribute -->
            <xsl:apply-templates select="@*" />
        </xsl:element>
    </xsl:element>
    <!-- recursive call on node() -->
    <xsl:apply-templates select="./*" mode="puke" />    
</xsl:template>

atributo Jogo de um determinado nó e exibi-los.

O uso CSS para formatar o HTML resultante:

<style>
.puke {
    background-color: #BDD6DE;
    clear: both;
}
.tagName, .attrName {
    float: left;
}
.tagText, .attrText {
    clear: right;
}
</style>

Já temos uma leitura programa * C Pro a partir de um banco de dados Oracle, ele chama um script perl que por sua vez executa alguns Java para extrair dados em formato XML do banco de dados acima referidas, para chamar um arquivo de lote para executar algum vbscript FTPing o arquivo para algum outro servidor. Eu estava realmente esperando por algo em Fortran.

As necessidades pergunta original de ser esclarecidos:

  • O que acontece com BValue e cValue na pergunta original? Existe uma razão por que eles não devem fazer parte da estrutura achatada?
  • Faça todos os elementos no documento XML tem 2 atributos ou isso é completamente arbitrária?
  • Há apenas 3 tipos de elementos e são sempre aninhados como mostrado no exemplo?
  • Pode seu element1 ser repetido em si ou isso é o elemento raiz do seu documento?

Em XSLT é possível escrever transformadores muito genéricos, mas muitas vezes é muito mais fácil de escrever uma folha de estilo para transformar um documento quando você pode tomar quaisquer restrições conhecidas em conta.

Eu usei uma versão expandida do modelo abaixo para achatar XML estruturado. Aviso: Houve algum código caso específico na versão original (que na verdade se transformou o XML em CSV) que eu só despojado e eu não testar esta versão.

A forma básica funciona deve ser clara: ele imprime tudo o que não tem filhos nó e de outra forma recursiva chama o modelo no nó () que faz ter filhos. Eu não acho que ele lida com atributos e comentários corretamente como é agora, mas isso não deve ser difícil de corrigir.

<?xml version="1.0" encoding="UTF-8"?>

<!-- XSL template to flatten structured XML, before converting to CSV. -->
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

    <xsl:strip-space elements="*" /> 

    <xsl:template match="/">
        <xsl:apply-templates select="//yourElementsToFlatten"/>
    </xsl:template>

    <xsl:template match="//yourElementsToFlatten">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:template>

    <xsl:template match="@*|node()">
        <xsl:choose>
            <!-- If the element has multiple childs, call this template 
                on its children to flatten it-->
            <xsl:when test="count(child::*) > 0">
                <xsl:apply-templates select="@*|node()"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:value-of select="text()" />
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top