Dlaczego XSLT domyślnie wypisuje cały tekst?

Witam wykonałem transformację, która upuszcza znacznik, jeśli jest null.

Chciałem sprawdzić, czy moja transformacja działa poprawnie, więc zamiast sprawdzać ją ręcznie, napisałem jeszcze jeden kod XSLT, który sprawdza obecność tego konkretnego znacznika w wyjściowym XML, jeśli jest null, to drugi XSLT powinien wypisać tekst "FOUND". (Właściwie nie potrzebuję jakiegoś wyjścia XML, ale używam tylko XSLT do wyszukiwania.)

Kiedy próbowałem z tym kodem XSL ::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
</xsl:stylesheet>

Wypisuje wszystkie dane tekstowe obecne w pliku XML,

Aby tego uniknąć, musiałem napisać ten kod::

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/SiebelMessage//SuppressCalendar[.!='']">
      FOUND
  </xsl:template>
  <xsl:template match="text()"/>
</xsl:stylesheet>

Dlaczego poprzedni kod wyświetla tekst, dlaczego powinienem nalegać, aby XSL ignorował cały inny tekst? jest to zachowanie wszystkich parserów XML lub tylko mojego własnego (używam parsera msxml).

 67
Author: Wayne Burkett, 2010-07-29

2 answers

Dlaczego poprzedni kod wypisuje tekst, dlaczego mam nalegać, aby xsl ignorował wszystkie inny tekst? czy to zachowanie wszystkie parsery XML lub tylko moje własne

Odkrywasz jedną z najbardziej podstawowych funkcji XSLT, jak określono w specyfikacji: wbudowane szablony XSLT.

Z Spec:

Istnieje wbudowana reguła szablonu do Zezwalaj na kontynuowanie przetwarzania rekurencyjnego w brak udanego wzorca dopasowanie przez wyraźną regułę szablonu w arkusz stylów. Ta zasada szablonu dotyczy zarówno węzłów elementów, jak i węzeł główny. Poniżej przedstawiamy odpowiednik wbudowanego szablonu reguła:

<xsl:template match="*|/">
  <xsl:apply-templates/>
</xsl:template>

Istnieje również wbudowana reguła szablonów dla każdego trybu, co pozwala na rekurencyjne przetwarzanie, aby kontynuować w tym samym tryb w przypadku braku pomyślnego dopasowanie wzorca za pomocą jawnego szablonu reguły w arkuszu stylów. Ten szablon reguła dotyczy zarówno węzłów elementów, jak i węzeł główny. Poniżej przedstawiamy odpowiednik wbudowanego szablonu Reguła dla trybu m.

<xsl:template match="*|/" mode="m">
  <xsl:apply-templates mode="m"/>
</xsl:template>

Istnieje również wbudowana reguła szablonów dla węzłów tekstowych i atrybutów, które kopiuje tekst przez:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

Wbudowana reguła szablonu dla instrukcje przetwarzania i uwagi to nic nie robić.

<xsl:template match="processing-instruction()|comment()"/>

Wbudowana reguła szablonu dla węzły przestrzeni nazw również nic nie robią. Nie ma wzoru, który może pasować do węzeł przestrzeni nazw; tak więc wbudowany szablon reguła jest jedynym szablonem reguła stosowana dla przestrzeni nazw węzły.

Wbudowane reguły szablonów to traktowane tak, jakby były importowane niejawnie przed arkuszem stylów i więc mają niższy priorytet importu niż wszystkie pozostałe zasady szablonu. Tak więc, autor może nadpisać wbudowany zasada szablonu poprzez włączenie wyraźnego zasada szablonu.

Tak więc zgłoszone zachowanie jest wynikiem zastosowanie wbudowanych szablonów-1.i 2. z wszystkich trzech.

Jest to dobry wzorzec projektowy XSLT do nadpisania wbudowanych szablonów własnymi, które będą wyświetlać komunikat o błędzie, gdy zostaną wywołane, aby programista od razu wiedział, że jego transformacja "przecieka": {]}

Na przykład, jeśli istnieje taki dokument XML:

<a>
  <b>
    <c>Don't want to see this</c>
  </b>
</a>

I jest przetwarzana z tą transformacją :

<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:template match="a|b">
   <xsl:copy>
      <xsl:attribute name="name">
        <xsl:value-of select="name()"/>
      </xsl:attribute>
      <xsl:apply-templates/>
   </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

Wynik is:

<a name="a">
   <b name="b">Don't want to see this</b>
</a>

I programista będzie bardzo zdezorientowany, jak pojawił się niechciany tekst.

Jednak wystarczy dodać to catch-all template pomaga uniknąć takiego zamieszania i natychmiast wyłapać błędy :

 <xsl:template match="*">
  <xsl:message terminate="no">
   WARNING: Unmatched element: <xsl:value-of select="name()"/>
  </xsl:message>

  <xsl:apply-templates/>
 </xsl:template>

Teraz, poza mylącym wyjściem, programista otrzymuje ostrzeżenie, które natychmiast wyjaśnia problem :

 WARNING: Unmatched element: c
 136
Author: Dimitre Novatchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-31 20:59:16

Istnieje kilka Wbudowanych reguł szablonów w XSL, z których jedną jest:

<xsl:template match="text()|@*">
  <xsl:value-of select="."/>
</xsl:template>

Wyświetla tekst.

 13
Author: Oded,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-29 06:40:22