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::*?

 22
Author: ROMANIA_engineer, 2011-03-22

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>&#10;</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.)

 37
Author: Wayne Burkett,
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.

 18
Author: Michael Kay,
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