复制子节点并使用XSL更改元素名称

时间:2014-06-10 01:32:58

标签: xml xslt xslt-2.0

我有来自供应商的源XML:

源XML

<?xml version="1.0" encoding="UTF-8"?>
<src:view name="books"
    xmlns="xyz.com/wow"
    xmlns:src="xyz.com/fun" 
    xmlns:xsi="w3.org/2001/XMLSchema-instance">
    <books>
        <title>Searching for Answers</title>
    </books>
    <books>
        <title>Get Rich Quick</title>   
    </books>
    <books>
        <title>Negotiating with the Grim Reaper</title> 
    </books>    
</src:view>

我想转换为具有根元素books的新文档,然后复制所有books元素,但将名称从books更改为books_record。文档将是任意的,( books 今天,小部件明天等),但是根的子元素的元素名称始终可以从/@name获得,这是供应商约定。

预期输出

<books>
   <books_record>
      <title>Searching for Answers</title>
   </books_record>
   <books_record>
      <title>Get Rich Quick</title>
   </books_record>
   <books_record>
      <title>Negotiating with the Grim Reaper</title>
   </books_record>
</books>

我管理了权利根元素并复制了所有子元素,但我不确定如何将所有<books>更改为<books_record>。而且,到目前为止我的效率和有效性是多少?我知道它有效,但不是100%确定它是否是最好的方法。

到目前为止

XSL(在michael.hor257k的帮助下更新)

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    exclude-result-prefixes="xsl" version="2.0">
    <xsl:output method="xml" version="1.0" encoding="UTF-8"
        indent="yes" />
    <xsl:strip-space elements="*" />

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*" />
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="/*">
    <xsl:variable name="rootElementName">
        <xsl:value-of select="@name" />
    </xsl:variable>     

    <xsl:element name="{$rootElementName}">      
            <xsl:apply-templates /> 
    </xsl:element>       

</xsl:template>

<xsl:template match="/*/node()">
    <xsl:variable name="rootElementName">
        <xsl:value-of select="/*/@name" />
    </xsl:variable>

    <xsl:element name="{$rootElementName}_record">      
            <xsl:apply-templates /> 
    </xsl:element>          
</xsl:template>
</xsl:transform>

1 个答案:

答案 0 :(得分:2)

我相信你可以将其简化为:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*" />
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

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

<xsl:template match="*[local-name()='books']">
    <books_record>
        <xsl:apply-templates />
    </books_record>
</xsl:template>

</xsl:transform>

当然,如果你知道输入的预期格式,你可以更明确 - 因此更短的更有效,例如:

<xsl:transform version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:src="xyz.com/fun" 
xmlns:wow="xyz.com/wow"
exclude-result-prefixes="src wow">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

<xsl:template match="/">
    <books>
        <xsl:for-each select="src:view/wow:books">
            <books_record>
                <title>
                    <xsl:value-of select="wow:title"/>
                </title>
            </books_record>
        </xsl:for-each>
    </books>
</xsl:template> 

</xsl:transform>

编辑:

如果我正确理解你的意思是&#34; generic&#34;,那么:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />

<xsl:variable name="tableName" select="/*/@name" />

<xsl:template match="*">
    <xsl:element name="{local-name()}">
        <xsl:copy-of select="@*" />
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="/*">
    <xsl:element name="{$tableName}">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="*/*">
     <xsl:element name="{$tableName}_record">
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:transform>

注意:

  1. 变量仅定义一次;
  2. 此部分不是必需的:
    exclude-result-prefixes="xsl"