2017-12-19 20 views
1

ノード名に基づいて子要素を持つすべてのノードにID属性を追加したいが、既に参照がある場合はインクリメントする。属性を追加することはできますが、以前の発生に基づいて属性を増やす方法は不明です。この中の任意のヘルプは大幅にxslのノード名(インクリメンタル)に基づいて属性を追加する

初期XML

<xml> 
    <individual> 
     <name> 
      <firstname>Me</firstname> 
      <lastname>Last</lastname> 
     </name> 
     <addresses> 
      <address> 
       <street>1234 Main</street> 
       <city>Anytown</city> 
       <state>TX</state> 
      </address> 
      <address> 
       <street>4321 Central Ave</street> 
       <city>Bixby</city> 
       <state>ND</state> 
      </address> 
     </addresses> 
     <employeers> 
      <employeer> 
       <name> 
        <firstname>Employer1</firstname> 
        <lastname>EmployerLast</lastname> 
       </name> 
       <addresses> 
        <address> 
         <street>1234 Employer1</street> 
         <city>Smallville</city> 
         <state>CT</state> 
        </address> 
       </addresses> 
      </employeer> 
      <employeer> 
       <name> 
        <firstname>Employer2</firstname> 
        <lastname>EmployerLast2</lastname> 
       </name> 
       <addresses> 
        <address> 
         <street>1234 Employer2</street> 
         <city>Nashville</city> 
         <state>TN</state> 
        </address> 
       </addresses> 
      </employeer> 
     </employeers> 
    </individual> 
</xml> 

望ましい結果

<xml> 
    <individual ID="indivdual_1"> 
     <name ID="name_1"> 
      <firstname>Me</firstname> 
      <lastname>Last</lastname> 
     </name> 
     <addresses ID="addresses_1"> 
      <address ID="address_1"> 
       <street>1234 Main</street> 
       <city>Anytown</city> 
       <state>TX</state> 
      </address> 
      <address ID="address_2"> 
       <street>4321 Central Ave</street> 
       <city>Bixby</city> 
       <state>ND</state> 
      </address> 
     </addresses> 
     <employeers ID="employeers_1"> 
      <employeer ID="employeer_1"> 
       <name ID="name_2"> 
        <firstname>Employer1</firstname> 
        <lastname>EmployerLast</lastname> 
       </name> 
       <addresses ID="addresses_2"> 
        <address ID="address_3"> 
         <street>1234 Employer1</street> 
         <city>Smallville</city> 
         <state>CT</state> 
        </address> 
       </addresses> 
      </employeer> 
      <employeer ID="employeer_2"> 
       <name ID="name_3"> 
        <firstname>Employer2</firstname> 
        <lastname>EmployerLast2</lastname> 
       </name> 
       <addresses ID="addresses_3"> 
        <address ID="address_4"> 
         <street>1234 Employer2</street> 
         <city>Nashville</city> 
         <state>TN</state> 
        </address> 
       </addresses> 
      </employeer> 
     </employeers> 
    </individual> 
</xml> 

をいただければ幸い私は、特定の要素の発生をカウントするために、次のコードを見つけましたが、どのように適用するかわかりませんよ特定のノードに数えます。

答えて

2

私はそれがxsl:numberための仕事だと思う:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

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

    <xsl:template match="/*//*[*]"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:attribute name="ID"><xsl:value-of select="local-name()"/>_<xsl:number level="any"/></xsl:attribute> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

http://xsltfiddle.liberty-development.net/b4GWV1を参照してください、それはあなたがこれは私が提案のだものよりもよりよい解決策である出力に

<xml> 
    <individual ID="individual_1"> 
     <name ID="name_1"> 
      <firstname>Me</firstname> 
      <lastname>Last</lastname> 
     </name> 
     <addresses ID="addresses_1"> 
      <address ID="address_1"> 
       <street>1234 Main</street> 
       <city>Anytown</city> 
       <state>TX</state> 
      </address> 
      <address ID="address_2"> 
       <street>4321 Central Ave</street> 
       <city>Bixby</city> 
       <state>ND</state> 
      </address> 
     </addresses> 
     <employeers ID="employeers_1"> 
      <employeer ID="employeer_1"> 
       <name ID="name_2"> 
        <firstname>Employer1</firstname> 
        <lastname>EmployerLast</lastname> 
       </name> 
       <addresses ID="addresses_2"> 
        <address ID="address_3"> 
         <street>1234 Employer1</street> 
         <city>Smallville</city> 
         <state>CT</state> 
        </address> 
       </addresses> 
      </employeer> 
      <employeer ID="employeer_2"> 
       <name ID="name_3"> 
        <firstname>Employer2</firstname> 
        <lastname>EmployerLast2</lastname> 
       </name> 
       <addresses ID="addresses_3"> 
        <address ID="address_4"> 
         <street>1234 Employer2</street> 
         <city>Nashville</city> 
         <state>TN</state> 
        </address> 
       </addresses> 
      </employeer> 
     </employeers> 
    </individual> 
</xml> 
+0

を掲載している入力を変換。 +1 – kjhughes

+0

うわー...これはシンプルだが効果的だ...私はこれを理解しようとしている私の髪を引っ張っただろう...ありがとう – mike

+0

xsl:numberを使って親ノードの数を得ることは可能ですか?ノード、属性をループするとき?私は自分の考えに基づいてコードを更新しましたが、希望どおりに動作するようには見えません。 http://xsltfiddle.liberty-development.net/bFukv89/1。 – mike

0

これを達成する1つの方法は、各要素のグローバルカウントを持つ置換テンプレートを作成することです。
name,individual,address,addresses,employeers,employeerの6つのテンプレートを意味します。

変数idxのグローバルカウントを取得するために、これらのテンプレートのそれぞれは//と一致します。次に、現在のノードをコピーで置き換え、新しいID属性を追加します。 アイデンティティテンプレートは、他のすべてのノードをコピーします。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/> 

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

<!-- global templates for specific element 'name' --> 
<xsl:template match="//name"> 
    <xsl:variable name="idx" select="count(preceding::name) + 1" /> 
    <xsl:copy> 
    <xsl:attribute name="ID"><xsl:value-of select="concat(local-name(),'_',$idx)" /></xsl:attribute> 
    <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

<!-- global templates for specific element 'address' --> 
<xsl:template match="//address"> 
    <xsl:variable name="idx" select="count(preceding::address) + 1" /> 
    <xsl:copy> 
    <xsl:attribute name="ID"><xsl:value-of select="concat(local-name(),'_',$idx)" /></xsl:attribute> 
    <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

<!-- global templates for specific element 'addresses' --> 
<xsl:template match="//addresses"> 
    <xsl:variable name="idx" select="count(preceding::addresses) + 1" /> 
    <xsl:copy> 
    <xsl:attribute name="ID"><xsl:value-of select="concat(local-name(),'_',$idx)" /></xsl:attribute> 
    <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

<!-- global templates for specific element 'individual' --> 
<xsl:template match="//individual"> 
    <xsl:variable name="idx" select="count(preceding::individual) + 1" /> 
    <xsl:copy> 
    <xsl:attribute name="ID"><xsl:value-of select="concat(local-name(),'_',$idx)" /></xsl:attribute> 
    <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

<!-- global templates for specific element 'employeers' --> 
<xsl:template match="//employeers"> 
    <xsl:variable name="idx" select="count(preceding::employeers) + 1" /> 
    <xsl:copy> 
    <xsl:attribute name="ID"><xsl:value-of select="concat(local-name(),'_',$idx)" /></xsl:attribute> 
    <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

<!-- global templates for specific element 'employeer' --> 
<xsl:template match="//employeer"> 
    <xsl:variable name="idx" select="count(preceding::employeer) + 1" /> 
    <xsl:copy> 
    <xsl:attribute name="ID"><xsl:value-of select="concat(local-name(),'_',$idx)" /></xsl:attribute> 
    <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 

これはXSLT-1.0ソリューションであり、出力は必要に応じて調整する必要があります。

関連する問題