Add attribute to each xml node xslt

2019-07-28 14:35发布

I'm trying to make a cope of a xml using xslt, please see example or below. Additional I like to add a attribute for each node which represents the xpath of the node. But I get the issue

XTDE0420: Cannot create an attribute node (xpath) whose parent is a document node

My example xml is:

<?xml version="1.0" encoding="utf-16"?>
<shiporder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" orderid="orderid1">
  <orderperson>orderperson1</orderperson>
  <shipto>
    <name>name1</name>
    <address>address1</address>
    <city>city1</city>
    <country>country1</country>
  </shipto>
  <item>
    <title>title1</title>
    <note>note1</note>
    <quantity>1</quantity>
    <price>1</price>
  </item>
  <item>
    <title>title2</title>
    <note>note2</note>
    <quantity>79228162514264337593543950335</quantity>
    <price>-79228162514264337593543950335</price>
  </item>
  <item>
    <title>title3</title>
    <note>note3</note>
    <quantity>2</quantity>
    <price>79228162514264337593543950335</price>
  </item>
  <item>
    <title>title4</title>
    <note>note4</note>
    <quantity>79228162514264337593543950334</quantity>
    <price>0.9</price>
  </item>
  <item>
    <title>title5</title>
    <note>note5</note>
    <quantity>3</quantity>
    <price>1.1</price>
  </item>
</shiporder>

And my xslt sheet for the transformation looks like:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:func="http://www.functx.com">
  <xsl:output method="xml" encoding="utf-8"/>

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:attribute name="xpath">
            <xsl:value-of select="func:getXpath(.)"/>
        </xsl:attribute>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

   <xsl:function name="func:createXPath" >
    <xsl:param name="pNode" as="node()"/>
    <xsl:value-of select="$pNode/ancestor-or-self::*/name()" separator="/"/>
  </xsl:function>

  <xsl:function name="func:getXpath">
  <xsl:param name="pNode" as="node()"/>
   <xsl:value-of select="$pNode/ancestor-or-self::*/(count(preceding-sibling::*) + 1)" separator="/" />
</xsl:function> 

</xsl:stylesheet>

Additional I like to combine the function for name and counter, that result looks like nodeName[2]/nodeName[5]/..

标签: xslt
1条回答
手持菜刀,她持情操
2楼-- · 2019-07-28 14:42

Instead of:

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

try:

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

Note:

  1. Your output method should be xml, not text;

  2. If you want to use xsl:function, then your version should be 2.0;

  3. Your first template is redundant.

查看更多
登录 后发表回答