2009-09-23 11 views
36

Używam XML do przechowywania małej listy kontaktów i próby napisania szablonu XSL, który przekształci go w plik CSV. Problem, który mam, dotyczy białych znaków na wyjściu.XSLT - usuń białe znaki z szablonu

Wyjście:

Friend, John, Smith, Home, 
     123 test, 
     Sebastopol, 
     California, 
     12345, 
    Home 1-800-123-4567, Personal [email protected] 

mam wcięty rozstawione zarówno plik/źródło XML i związane z szablonu XSL, aby łatwiej było czytać i rozwijać, ale to wszystko extra białe miejsca jest coraz się do wyjścia . Sam XML nie ma dodatkowych białych znaków wewnątrz węzłów, poza nimi po to, by formatować, i to samo dotyczy XSLT.

Aby plik CSV był ważny, każdy wpis musi znajdować się we własnej linii, a nie w podziale. Poza usunięciem wszystkich dodatkowych białych znaków z XML i XSLT (co czyni je tylko jedną długą linią kodu), czy istnieje inny sposób na pozbycie się białych znaków na wyjściu?

Edit: Oto mała próbka XML:

<PHONEBOOK> 
    <LISTING> 
     <FIRST>John</FIRST> 
     <LAST>Smith</LAST> 
     <ADDRESS TYPE="Home"> 
      <STREET>123 test</STREET> 
      <CITY>Sebastopol</CITY> 
      <STATE>California</STATE> 
      <ZIP>12345</ZIP> 
     </ADDRESS> 
     <PHONE>1-800-123-4567</PHONE> 
     <EMAIL>[email protected]</EMAIL> 
     <RELATION>Friend</RELATION> 
    </LISTING> 
</PHONEBOOK> 

A oto XSLT:

<?xml version="1.0" ?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="text" /> 

<xsl:template match="/"> 
    <xsl:for-each select="//LISTING"> 
    <xsl:value-of select="RELATION" /><xsl:text>, </xsl:text> 
    <xsl:value-of select="FIRST" /><xsl:text>, </xsl:text> 
    <xsl:value-of select="LAST" /><xsl:text>, </xsl:text> 

    <xsl:if test="ADDRESS"> 
    <xsl:for-each select="ADDRESS"> 
     <xsl:choose> 
     <xsl:when test="@TYPE"> 
     <xsl:value-of select="@TYPE" />, 
     </xsl:when> 
      <xsl:otherwise> 
      <xsl:text>Home </xsl:text> 
      </xsl:otherwise> 
     </xsl:choose> 
     <xsl:value-of select="STREET" />, 
     <xsl:value-of select="CITY" />, 
     <xsl:value-of select="STATE" />, 
     <xsl:value-of select="ZIP" />, 
    </xsl:for-each> 
    </xsl:if> 

    <xsl:for-each select="PHONE"> 
     <xsl:choose> 
     <xsl:when test="@TYPE"> 
     <xsl:value-of select="@TYPE" /> 
     </xsl:when> 
     <xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise> 
     </xsl:choose> 
    <xsl:value-of select="." /><xsl:text >, </xsl:text> 
    </xsl:for-each> 

    <xsl:if test="EMAIL"> 
    <xsl:for-each select="EMAIL"> 
     <xsl:choose> 
     <xsl:when test="@TYPE"> 
     <xsl:value-of select="@TYPE" /><xsl:text > </xsl:text> 
     </xsl:when> 
     <xsl:otherwise><xsl:text >Personal </xsl:text></xsl:otherwise> 
     </xsl:choose> 
     <xsl:value-of select="." /><xsl:text >, </xsl:text> 
    </xsl:for-each> 
    </xsl:if> 
    <xsl:text>&#10;&#13;</xsl:text> 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 
+4

Dlaczego używasz 'disable-output-escaping' na każdym' '? Nie potrzebujesz tego dla ''. Od specyfikacji XSLT 1.0: "Metoda wyjścia tekstowego ignoruje atrybut disable-output-escaping, ponieważ nie wykonuje żadnego wyprowadzania wyjścia." –

Odpowiedz

74

W XSLT domyślnie zapisywana jest biała ramka, ponieważ może ona być bardzo trafna.

Najlepszym sposobem zapobiegania niechcianej przestrzeni białej na wydruku nie jest jej tworzenie.Nie rób:

<xsl:template match="foo"> 
    foo 
</xsl:template> 

bo to "\n··foo\n", z punktu widzenia procesora. Zamiast tego białe spacje w arkuszu stylów są ignorowane, o ile występują tylko między elementami XML. Mówiąc krótko: nigdy nie używaj "nagiego" tekstu w swoim kodzie XSLT, zawsze umieszczaj go w elemencie.

Ponadto, stosując niespecyficzne:

<xsl:apply-templates /> 

jest problematyczne, ponieważ domyślna reguła XSLT dla tekstu węzłów mówi „skopiuj je do wyjścia”. Dotyczy to również węzłów "tylko białych przestrzeni". Na przykład:

<xml> 
    <data> value </data> 
</xml> 

zawiera trzy węzły tekstowe:

  1. "\n··" (zaraz po <xml>)
  2. "·value·"
  3. "\n" (tuż przed </xml>)

aby uniknąć # 1 i # 3 wkradają się do wyjścia (które jest najczęstszą przyczyną niechcianych spacjami), można zastąpić domyślne reguły dla węzłów tekstowych deklarując pusty szablon:

<xsl:template match="text()" /> 

Wszystkie węzły tekstowe są teraz wyciszony i wyjście tekst musi zostać utworzony wyraźnie:

<xsl:value-of select="data" /> 

Aby usunąć white-space z wartości, można użyć funkcji normalize-space() XSLT:

<xsl:value-of select="normalize-space(data)" /> 

Ale uważaj, ponieważ funkcja normalizuje żadnych wHI te-space znalezione w ciągu znaków, np. "·value··1·" stanie się "value·1".

Dodatkowo można użyć elementów <xsl:strip-space> i <xsl:preserve-space>, chociaż zazwyczaj nie jest to konieczne (i osobiście wolę jawną obsługę przestrzeni białej, jak wskazano powyżej).

7

Domyślnie szablony XSLT mieć <xsl:preserve-space> zestaw, który będzie na bieżąco spacje w produkcji . Możesz dodać <xsl:strip-space elements="*">, aby przekazać je do gdzie usunąć białe spacje.

Możesz również dołączyć dyrektywę normalizować-Space, tak jak poniżej:

<xsl:template match="text()"><xsl:value-of select="normalize-space(.)"/></xsl:template> 

Oto example for preserve/strip space from W3 Schools.

+9

W3 Schools! = W3 Reference, odniesienie W3 jest tutaj -> http://www.w3.org/TR/xslt#strip – Skuld

2

Jeśli chodzi o usuwanie zakładek, ale zachowywanie oddzielnych linii, spróbowałem następującego podejścia XSLT 1.0 i działa całkiem dobrze. Korzystanie z wersji 1.0 lub 2.0 zależy w dużej mierze od platformy, z której korzystasz. Wygląda na to, że technologia .NET nadal zależy od XSLT 1.0, więc ograniczasz się do bardzo niechlujnych szablonów (patrz poniżej). Jeśli używasz Javy lub czegoś innego, odwołaj się do znacznie czystszego podejścia XSLT 2.0 wymienionego na samym dole.

Te przykłady mają być rozszerzone przez Ciebie, aby spełnić Twoje szczególne potrzeby. Używam tutaj kart jako przykładu, ale powinno to być na tyle ogólne, aby można je było rozszerzyć.

XML:

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

       dsalkfjdsaflkj 

      lkasdfjlsdkfaj 
</text> 

... i szablon XSLT 1.0 (wymagana jeśli używasz .NET):

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:template name="search-and-replace"> 
    <xsl:param name="input"/> 
    <xsl:param name="search-string"/> 
    <xsl:param name="replace-string"/> 
    <xsl:choose> 
    <xsl:when test="$search-string and 
        contains($input,$search-string)"> 
     <xsl:value-of 
      select="substring-before($input,$search-string)"/> 
     <xsl:value-of select="$replace-string"/> 
     <xsl:call-template name="search-and-replace"> 
     <xsl:with-param name="input" 
       select="substring-after($input,$search-string)"/> 
     <xsl:with-param name="search-string" 
       select="$search-string"/> 
     <xsl:with-param name="replace-string" 
       select="$replace-string"/> 
     </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="$input"/> 
    </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template>     
    <xsl:template match="text"> 
    <xsl:call-template name="search-and-replace"> 
    <xsl:with-param name="input" select="text()" /> 
    <xsl:with-param name="search-string" select="'&#x9;'" /> 
    <xsl:with-param name="replace-string" select="''" /> 
    </xsl:call-template>  
    </xsl:template> 
</xsl:stylesheet> 

XSLT 2.0 sprawia, że ​​to banalne z replace funkcję:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     exclude-result-prefixes="xs" 
     version="2.0"> 
<xsl:template match="text"> 
    <xsl:value-of select="replace(text(), '&#x9;', '')" /> 
</xsl:template> 
</xsl:stylesheet> 
1

Inni już wskazywali na ogólny problem. Specyficzny dla swojego arkusza stylów jest to, że zapomniał <xsl:text> dla przecinkami:

<xsl:choose> 
    <xsl:when test="@TYPE"> 
    <xsl:value-of select="@TYPE" />, 
    </xsl:when> 
    <xsl:otherwise>Home </xsl:otherwise> 
    </xsl:choose> 
    <xsl:value-of select="STREET" />, 
    <xsl:value-of select="CITY" />, 
    <xsl:value-of select="STATE" />, 
    <xsl:value-of select="ZIP" />, 

To sprawia, że ​​każdy przecinek po spacji znaczące, a więc kończy się na wyjściu to. Jeśli zawiniesz każdy przecinek w <xsl:text>, problem zniknie.

Pozbądź się także tego disable-output-escaping. Nic tu nie robi, ponieważ nie wyprowadzasz XML.

1

Dodaj jeden szablon do swojego XSLT

<xsl:template match="text()"/> 
+0

Dlaczego? W jaki sposób? Dziękuję ci za odpowiedź, ale zawsze dawaj więcej informacji. – peterh

0

Moja previouse odpowiedź jest błędna, wszystkie przecinki muszą być wyprowadzane poprzez tag „tekst”

<?xml version="1.0" ?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 
    <xsl:template match="/PHONEBOOK"> 
     <xsl:for-each select="LISTING"> 
      <xsl:value-of select="RELATION" /><xsl:text>, </xsl:text> 
      <xsl:value-of select="FIRST" /><xsl:text>, </xsl:text> 
      <xsl:value-of select="LAST" /><xsl:text>, </xsl:text> 

       <xsl:for-each select="ADDRESS"> 
        <xsl:choose> 
         <xsl:when test="@TYPE"> 
          <xsl:value-of select="@TYPE" /><xsl:text>,</xsl:text> 
         </xsl:when> 
         <xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise> 
        </xsl:choose> 
       <xsl:value-of select="STREET/text()" /><xsl:text>,</xsl:text> 
        <xsl:value-of select="CITY/text()" /><xsl:text>,</xsl:text> 
        <xsl:value-of select="STATE/text()" /><xsl:text>,</xsl:text> 
        <xsl:value-of select="ZIP/text()" /><xsl:text>,</xsl:text> 
       </xsl:for-each> 

      <xsl:for-each select="PHONE"> 
       <xsl:choose> 
        <xsl:when test="@TYPE"> 
         <xsl:value-of select="@TYPE" /> 
        </xsl:when> 
        <xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise> 
       </xsl:choose> 
       <xsl:value-of select="." /><xsl:text >, </xsl:text> 
      </xsl:for-each> 

      <xsl:if test="EMAIL"> 
       <xsl:for-each select="EMAIL"> 
        <xsl:choose> 
         <xsl:when test="@TYPE"> 
          <xsl:value-of select="@TYPE" /><xsl:text > </xsl:text> 
         </xsl:when> 
         <xsl:otherwise><xsl:text >Personal </xsl:text></xsl:otherwise> 
        </xsl:choose> 
        <xsl:value-of select="." /><xsl:text >, </xsl:text> 
       </xsl:for-each> 
      </xsl:if> 
      <xsl:text>&#10;&#13;</xsl:text> 
     </xsl:for-each> 
    </xsl:template> 
    <xsl:template match="text()|@*"> 
     <xsl:text>-</xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 
0

zmodyfikować kod, który zwykliśmy formacie RAW xml plik poprzez usunięcie poniższych linii usunie dodatkowe puste białe spacje dodane do eksportowanego programu Excel.

Podczas formatowania z wciętym systemem właściwości dodawane są dodatkowe puste białe spacje.

Skomentuj wiersze związane z formatowaniem xml jak poniżej i spróbuj.

Powiązane problemy