2009-03-17 17 views
17

Mamy obecny system, który wyprowadza plik XML, który jest w następującym formacie:Konwersja elementy XML do atrybutów XML za pomocą XSLT

<INVENTORY> 
    <ITEM> 
     <SERIALNUMBER>something</SERIALNUMBER> 
     <LOCATION>something</LOCATION> 
     <BARCODE>something</BARCODE> 
    </ITEM> 
</INVENTORY> 

muszę korzystać z tych danych, aby załadować do standardowego .NET 2.0 siatce . Ale siatka musi być XML w następującym formacie:

<INVENTORY> 
    <ITEM serialNumber="something" location="something" barcode="something"> 
    </ITEM> 
</INVENTORY> 

tj węzły potomne elementu muszą być przekształcone atrybutów węzła poz.

Czy ktoś wie, jak można to zrobić za pomocą XSLT?

+0

Proszę przeczytać dokumentację znaczników, potrzebujesz 4 spacji lub tabulacji, aby SO rozpoznał kod. – AnthonyWJones

+0

Przyjęta przez ciebie odpowiedź nie daje oczekiwanego rezultatu !!! Jedna nazwa atrybutu musi być "serialNumber", przyjęte rozwiązanie generuje "numer seryjny". Następnym razem nie wprowadzaj w błąd ludzi, którzy poświęcają swój czas na pomoc. –

Odpowiedz

27

To powinno działać:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="INVENTORY"> 
    <INVENTORY> 
     <xsl:apply-templates/> 
    </INVENTORY> 
    </xsl:template> 

    <xsl:template match="ITEM"> 
    <ITEM> 
     <xsl:for-each select="*"> 
     <xsl:attribute name="{name()}"> 
      <xsl:value-of select="text()"/> 
     </xsl:attribute> 

     </xsl:for-each> 
    </ITEM> 
    </xsl:template> 
</xsl:stylesheet> 

HTH

+0

Dzięki za wszystkie sugestie, ale ten wydaje się być najprostszym i najbardziej dynamicznym rozwiązaniem :) i pracował dla mnie :) – eMTeeN

2

To powinno wystarczyć:

<xsl:for-each select="//ITEM"> 
    <xsl:element name="ITEM"> 
     <xsl:attribute name="serialNumber"> 
     <xsl:value-of select="SERIALNUMBER"/> 
     </xsl:attribute> 
     <xsl:attribute name="location"> 
     <xsl:value-of select="LOCATION"/> 
     </xsl:attribute> 
     <xsl:attribute name="barcode"> 
     <xsl:value-of select="BARCODE"/> 
     </xsl:attribute> 
    </xsl:element> 
    </xsl:for-each> 

lub używając skrótu Dawida:

<xsl:for-each select="//ITEM"> 
    <ITEM serialNumber="{SERIALNUMBER}" location="{LOCATION}" barcode="{BARCODE}"/> 
</xsl:for-each> 
2

Jeśli źródło wygląda następująco:

<row><a>1</a><b>2</b></row> 

i chcesz to wyglądać to:

<row a="1" b="2" /> 

wówczas XSLT powinno działać:

<xsl:template match="row"> 
    <row a="{a}" b="{b}" /> 
</xsl:template> 
4

Te dwa szablony powinien to zrobić: -

<xsl:template match="ITEM"> 
    <ITEM serialNumber="{SERIALNUMBER}" location="{LOCATION}" barcode="{BARCODE}" /> 
</xsl:template> 

<xsl:template match="INVENTORY"> 
    <INVENTORY> 
     <xsl:apply-templates /> 
    </INVENTORY> 
</xsl:template> 
4

Tutaj prawdopodobnie najprostsze soluti na że będzie konwertować dzieciom elementy ITEM do jego atrybutów i będzie reprodukować wszystkiego innego jak to, podczas konwersji nazw elementów do dowolnych nazw atrybutów:

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

    <xsl:variable name="vrtfNameMapping"> 
    <item name="SERIALNUMBER" newName="serialNumber"/> 
    <item name="LOCATION" newName="location"/> 
    <item name="BARCODE" newName="barcode"/> 
    </xsl:variable> 
<!--            --> 
    <xsl:variable name="vNameMapping" select= 
    "document('')/*/xsl:variable[@name='vrtfNameMapping']"/> 
<!--            --> 

    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
    </xsl:template> 
<!--            --> 
    <xsl:template match="ITEM/*"> 
    <xsl:attribute name= 
    "{$vNameMapping/*[@name=name(current())]/@newName}"> 
     <xsl:value-of select="."/> 
    </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

gdy powyższe transformacji jest stosowane na pod warunkiem dokument XML:

<INVENTORY> 
    <ITEM> 
     <SERIALNUMBER>something</SERIALNUMBER> 
     <LOCATION>something</LOCATION> 
     <BARCODE>something</BARCODE> 
    </ITEM> 
</INVENTORY> 

poszukiwanych wynik jest produkowany:

<INVENTORY> 
    <ITEM serialNumber="something" location="something" barcode="something"/> 
</INVENTORY> 

Należy pamiętać następujące:

  1. wykorzystaniu identity rule

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

  3. Zastosowanie zmiennego vrtfNameMapping bez funkcji xxx:node-set() przedłużacza .

  4. Fakt, że obsługujemy mapowanie między nazwą a nazwą nową, nie tylko prostą obudową dolną.

+0

Nie wygląda tak, jak ta transformacja działa. Nie daje żadnego wyniku. Tylko w ten sposób: Mark

+0

@Mark, oznacza to, że albo mają procesor XSLT buggy, lub nie zostały skopiowane i wklejone dokładnie Dokument XML i transformacja. Właśnie ponownie wykonałem transformację - ten sam wynik jest uzyskiwany przy użyciu kilku procesorów XSLT –