Różnica między: child:: node() a child::*
Właśnie napisałem XSLT, który na początku nie działał.
Musiałem zmienić nazwę wszystkich dzieci <Recordset>
na <C>
:
<?xml version="1.0" encoding="utf-8"?>
<Record>
<Recordset>
<company>102</company>
<store>1801</store>
....
</Recordset>
<Recordset>
....
</Recordset>
</Record>
Użyłem następującego XSLT:
<xsl:template match="Record/Recordset/child::*">
<xsl:element name="C">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
Działa i zmienia nazwę wszystkich dzieci <Recordset>
na <C>
.
Ale najpierw mój mecz w szablonie wyglądał tak:
<xsl:template match="Record/Recordset/child::node()">
Mój pomysł był taki, że każde dziecko <Recordset>
jest węzłem, więc node()
byłoby odpowiednie.
Zadziałało, ale dodało dodatkowe <C/>
dla każdego dziecka.
Jaka jest różnica między child::node()
i child::*
?
2 answers
child::node()
pasuje do każdego węzła, który nie jest węzłem atrybutów, węzłem przestrzeni nazw ani węzłem dokumentu. Oznacza to, że dopasowuje instrukcje przetwarzania, komentarze i węzły tekstowe.
child::*
dopasowuje tylko elementy.
Patrz sekcja 5.5.3 spec:
Węzeł wzorca () pasuje do wszystkich węzłów wybrane przez wyrażenie korzeń(.) / / (child-or-top:: node ()), że jest, wszystkie elementy, tekst, komentarz i przetwarzanie węzłów instrukcji, czy lub nie mają rodziców. Nie dopasuj atrybut lub węzły przestrzeni nazw ponieważ wyrażenie nie wybiera węzły korzystające z atrybutu lub przestrzeni nazw siekiery. Nie pasuje do węzłów dokumentu ponieważ dla kompatybilności wstecznej powody, dla których oś dziecięca lub górna nie dopasuj węzeł dokumentu.
Aktualizacja: odpowiedź Michaela zainspirowała następujący arkusz stylów. Użyj go do testowania typów węzłów w trakcie ich przetwarzania:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/|node()">
<xsl:call-template name="type" />
<xsl:text> [ </xsl:text>
<xsl:value-of select="." />
<xsl:text> </xsl:text>
<xsl:apply-templates select="node()" />
<xsl:text> ] </xsl:text>
</xsl:template>
<xsl:template name="type">
<xsl:choose>
<xsl:when test="count(.|/)=1">
<xsl:text>Root</xsl:text>
</xsl:when>
<xsl:when test="self::*">
<xsl:text>Element </xsl:text>
<xsl:value-of select="name()" />
</xsl:when>
<xsl:when test="self::text()">
<xsl:text>Text</xsl:text>
</xsl:when>
<xsl:when test="self::comment()">
<xsl:text>Comment</xsl:text>
</xsl:when>
<xsl:when test="self::processing-instruction()">
<xsl:text>PI</xsl:text>
</xsl:when>
<xsl:when test="count(.|../@*)=count(../@*)">
<xsl:text>Attribute</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Zmodyfikuj to, co jest dopasowane/wybrane do sprawdź inne wzory. Na przykład, następujące wejście:
<A attr="test" other="val">
<B/>
<C>some value</C>
<!-- a comment -->
<D/>
</A>
Produkuje następujące wyjście:
Root [
some value
Element A [
some value
Text [
] Element B [
] Text [
] Element C [ some value
Text [ some value
] ] Text [
] Comment [ a comment
] Text [
] Element D [
] Text [
] ] ]
Specjalne podziękowania dla tej strony za rozpoczęcie testów typu node. (Szczególnie pasuje, że jedna z odpowiedzi Michaela sprzed ponad sześciu lat też się tam pojawia.)
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
2011-03-22 22:34:42
Aby rozwinąć odpowiedź lwburka, jeśli twój XML wygląda tak:
<A>
<B/>
<C/>
<D/>
</A>
Wtedy element A ma 7 węzłów potomnych; trzy z nich to elementy, cztery to węzły tekstowe. Wyrażenie child::node()
pasuje do wszystkich 7, podczas gdy child::*
pasuje Tylko do elementów.
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
2011-03-22 21:12:18