2008-11-25 4 views
1

J'ai une définition XML qui contient un élément avec des éléments enfants. Par exemple:Génération de SQL à l'aide de XML et de XSLT

<a> 
<b> 
    <c>C</c> 
    <d>D</d> 
</b> 
</a> 

J'ai un XSLT avec une sortie de texte. Par exemple:

<xsl...> 
    <xsl:output method="text" indent="yes"/> 
    <xsl:template match="/"> 
    <xsl:copy-of select="https://stackoverflow.com/a/b" /> 
    ... 

Je veux copier l'ensemble de l'élément b et ses enfants dans une chaîne enlevé par des espaces afin que je puisse générer une requête SQL. Par exemple:

select * from some-table where xml = '<b><c>C</c><d>D</d></b>' 

Au moment de la copie est de trouver l'élément b, mais tous les éléments déposer et des informations d'attributs ne laissant que le contenu du texte dans chaque. Je pense que cela pourrait être lié au type de sortie.

Des idées?

Répondre

-1

Voici comment cela peut se faire:

<xsl:output method="xml" /> 

<xsl:template match="/"><xsl:apply-templates select="https://stackoverflow.com/a/b" mode="normalize-space" /></xsl:template> 

<xsl:template match="text()" mode="normalize-space"><xsl:value-of select="normalize-space(.)" /></xsl:template> 
<xsl:template match="@*|node()" mode="normalize-space"><xsl:copy><xsl:apply-templates select="@*|node()" mode="normalize-space" /></xsl:copy></xsl:template> 

Cette méthode noeuds copie, avec des nœuds et des attributs namespaces. La méthode nécessite que la sortie soit "xml" (pas "text" comme dans l'exemple original). Il utilise un modèle personnalisé pour tous les nœuds TEXT pour normaliser l'espace à l'intérieur d'eux (supprimer les espaces avant/arrière, condenser plusieurs espaces dans un seul espace). Ensuite, il utilise un simple modèle "d'identité" qui copie tous les nœuds et leurs attributs. Les deux modèles utilisent le mode spécial pour ne pas interférer avec le reste de XSL. Malheureusement, le processeur XSLT copie tous les nœuds "inconnus" à l'intérieur de la balise xsl: template dans le document de sortie et les espaces sont l'un de ces nœuds. C'est pourquoi tous ces modèles doivent être écrits sur une ligne sans espaces supplémentaires. PS Bien que, je suis d'accord que la recherche d'un XML normalisé dans le SGBDR est un peu bizarre.

+0

Bonne réponse, mais j'ai besoin de quelque chose avec une sortie de texte. Le peu de XSLT que j'ai ajouté m'a presque tout fait, mais n'a pas très bien traité les attributs. L'original était de sortir XML en SQL. Merci. –

1

Votre instruction SQL me fait peur. XML est sensible à la casse et votre comparaison risque d'échouer si l'entrée XML et XSLT (y compris tous les éléments, attributs et valeurs) ne sont pas traitées exactement comme celles utilisées dans l'insertion de base de données d'origine. Je crois qu'Oracle (certain) et SQL Server (je crois) ont des mécanismes pour faire une requête sur une colonne contenant du XML d'une manière plus conviviale pour XML (par exemple, en utilisant XPath).

Qu'essayez-vous exactement de faire? Votre problème semble plus profond que de simplement transformer ce XSLT correctement.

+0

Le point de la question n'est pas le contenu du XML ou de la requête, mais réellement la copie de XML en texte brut. –

+0

SQL Server 2000 (base de données cible) prend en charge la génération XML mais appelle l'analyseur MSXML. Dans les coulisses, cela a l'effet de manger dans la mémoire utilisée par SQL Server (environ un tiers me dit-on). Ce n'est pas souhaitable car cela se retrouvera dans un système de performance critique. –

+0

support xml intégré décent est apparu dans SQL Server 2005 –

1

Peut-être un peu trop difficile une tâche pour XSLT. Le plus proche que je peux obtenir est la suivante:

<xsl:template match="b//*|node()"> 
    <xsl:copy> 
     <xsl:text>&lt;</xsl:text> 
     <xsl:value-of select="name()"/> 
     <xsl:text>&gt;</xsl:text> 
     <xsl:value-of select="text()"/> 
     <xsl:apply-templates select="*"/> 
     <xsl:text>&lt;/</xsl:text> 
     <xsl:value-of select="name()"/> 
     <xsl:text>&gt;</xsl:text> 
    </xsl:copy> 
    </xsl:template> 

et est appelé à:

<xsl:apply-templates select="https://stackoverflow.com/a/b/self::*"/> 

Ce produit les suivantes:

<b> 
    <c>C</c> 
    <d>D</d> 
</b> 

où ma "solution" tombe est lorsque les éléments avoir des attributs. Si b avait un attribut, la valeur de l'attribut est écrite. Je ne peux pas trouver un moyen d'écrire des attributs au fur et à mesure qu'ils sont rencontrés ...

Des idées?