Dodawanie atrybutu do węzła

Próbuję dodać atrybut do węzła, jeśli wartość węzła potomnego jest równa jakiemuś łańcuchowi znaków.

Mam główną.plik xml
<Employees>    
 <Employee>     
 <countryid>32</countryid>
 <id name="id">1</id>
 <firstname >ABC</firstname>
 <lastname >XYZ</lastname>     
 </Employee>
 <Employee>     
 <countryid>100</countryid>
 <id name="id">2</id>
 <firstname >ddd</firstname>
 <lastname >ggg</lastname>     
 </Employee>
 </Employees>    

Powiedzmy więc, że jeśli identyfikator kraju jest równy 32, to powinien dodać atrybut country=32 do węzła pracownika. Wyjście powinno być jak poniżej:

Wyjście.xml

 <Employees>    
 <Employee countryid="32">     
 <countryid>32</countryid>
 <id name="id">1</id>
 <firstname >ABC</firstname>
 <lastname >XYZ</lastname>     
 </Employee>
 <Employee>     
 <countryid>100</countryid>
 <id name="id">2</id>
 <firstname >ddd</firstname>
 <lastname >ggg</lastname>     
 </Employee>
 </Employees>    

Używam poniższego skryptu, ale pojawia się błąd, że węzeł atrybutu nie może być utworzony po element.:

Transformacja.xsl


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

<xsl:template match="Employees/Employee/countryid[.=32']">
  <xsl:attribute name="countryid">32</xsl:attribute>
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>
Każda pomoc będzie mile widziana. Również możemy przekazać countryid jako wartości rozdzielone przecinkami tak, że mogę przekazać 32,100, a następnie powinien dodać atrybut do wszystkich pasujących węzłów. Dzięki.
Author: atif, 2011-01-28

2 answers

Poza dobrą odpowiedzią Dimitre ' a, arkusz stylów XSLT 2.0:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="pCountry" select="'32,100'"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Employee[countryid = tokenize($pCountry,',')]">
        <Employee countryid="{countryid}">
            <xsl:apply-templates select="@*|node()"/>
        </Employee>
    </xsl:template>
</xsl:stylesheet>

Wyjście:

<Employees>
    <Employee countryid="32">
        <countryid>32</countryid>
        <id name="id">1</id>
        <firstname>ABC</firstname>
        <lastname>XYZ</lastname>
    </Employee>
    <Employee countryid="100">
        <countryid>100</countryid>
        <id name="id">2</id>
        <firstname>ddd</firstname>
        <lastname>ggg</lastname>
    </Employee>
</Employees>

Notatka : Existencial comparison with sequence, param / variable reference in patterns.

Inne podejście przy założeniu, że countryid jest zawsze pierwszym dzieckiem:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:param name="pCountry" select="'32,100'"/>
    <xsl:template match="node()|@*" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="countryid[. = tokenize($pCountry,',')]">
        <xsl:attribute name="countryid">
            <xsl:value-of select="."/>
        </xsl:attribute>
        <xsl:call-template name="identity"/>
    </xsl:template>
</xsl:stylesheet>

Uwaga : Teraz xsl:strip-space instrukcja jest ważna (unika węzła tekstu wyjściowego przed atrybutem)

 5
Author: ,
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-01-28 13:35:21

Część 1 .

Więc powiedzmy, że identyfikator kraju jest równe 32 wtedy należy dodać atrybut country = 32 To Employee node.

Ta transformacja :

<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="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Employee[countryid=32]">
  <Employee countryid="{countryid}">
   <xsl:apply-templates select="@*|node()"/>
  </Employee>
 </xsl:template>
</xsl:stylesheet>

W przypadku zastosowania na dostarczonym dokumencie XML :

<Employees>
    <Employee>
        <countryid>32</countryid>
        <id name="id">1</id>
        <firstname >ABC</firstname>
        <lastname >XYZ</lastname>
    </Employee>
    <Employee>
        <countryid>100</countryid>
        <id name="id">2</id>
        <firstname >ddd</firstname>
        <lastname >ggg</lastname>
    </Employee>
</Employees>

Tworzy pożądany, poprawny wynik :

<Employees>
   <Employee countryid="32">
      <countryid>32</countryid>
      <id name="id">1</id>
      <firstname>ABC</firstname>
      <lastname>XYZ</lastname>
   </Employee>
   <Employee>
      <countryid>100</countryid>
      <id name="id">2</id>
      <firstname>ddd</firstname>
      <lastname>ggg</lastname>
   </Employee>
</Employees>

Wyjaśnienie :

  1. Reguła identity rule jest używana do kopiowania każdego węzła jako-is. Używanie i nadpisywanie reguły tożsamości (szablonu) jest najbardziej fundamentalnym i potężnym wzorcem projektowym XSLT.

  2. Istnieje tylko jeden szablon, który nadpisuje regułę tożsamości dla określonych węzłów -- Employee elementy, które mają potomek countryid z wartością łańcuchową (przekonwertowaną na liczbę) 32. Ten szablon dodaje atrybut countryid do elementu Employee i stosuje szablony, aby wznowić aktywność reguły tożsamości i skopiować Wszystko inne tak, jak jest.

Część 2.

Możemy również przekazać countryid jako przecinek seprated wartości tak, że mogę przejść 32,100, a następnie należy dodać atrybut do wszystkich pasujących węzłów

Ta transformacja :

<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:param name="pIds" select="'32,100'"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Employee">
  <Employee>
   <xsl:if test=
     "contains(concat(',',$pIds,','),
               concat(',',countryid,',')
               )">
    <xsl:attribute name="countryid">
      <xsl:value-of select="countryid"/>
    </xsl:attribute>
   </xsl:if>
   <xsl:apply-templates select="@*|node()"/>
  </Employee>
 </xsl:template>
</xsl:stylesheet>

Po zastosowaniu do tego samego dokumentu XML (powyżej), generuje pożądany, poprawny wynik :

<Employees>
   <Employee countryid="32">
      <countryid>32</countryid>
      <id name="id">1</id>
      <firstname>ABC</firstname>
      <lastname>XYZ</lastname>
   </Employee>
   <Employee countryid="100">
      <countryid>100</countryid>
      <id name="id">2</id>
      <firstname>ddd</firstname>
      <lastname>ggg</lastname>
   </Employee>
</Employees>
 11
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
2011-01-28 05:18:25