使用xslt将xml命名空间和属性复制到其他节点

时间:2012-05-29 14:34:39

标签: xml xslt xslt-2.0

所以我是xslt的新手,使用它2周后,现在遇到了将命名空间和属性从一个节点复制到另一个节点的问题。 我需要将名称空间和属性复制到另一个节点,删除根节点并删除一些不在新节点中的节点。第二部分删除节点可以在其他转换中完成,如果它更容易,我认为应该是。

这是输入文件:

<?xml version="1.0" encoding="UTF-8"?>
<xmi:XMI xmlns:namespace1="http://namespace" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" attribute1="some1">

<mode>
<node0>0</node0>

<node1 attribute2="some2"> 
    <child1 name="a" id="1"/>
    <child2 name="b" id="2"/>
</node1>

</mode>

<extra1 id="1"/>
<extra2 id="3"/>

<xmi:XMI>

我需要的输出:

<?xml version="1.0" encoding="UTF-8"?>

<node1 xmlns:namespace1="http://namespace" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" attribute1="some1" attribute2="some2" > 
    <child1 name="a" id="1"/>
    <child2 name="b" id="2"/>
</node1>
<extra1 id="1"/>

可能以后需要保留xmi:XMI节点只删除除node1和extra1之外的其他节点,但认为这个带有修改的xsl会有所帮助:

<xsl:stylesheet 
xmlns:xls="http://www.w3.org/1999/XSL/Transform" 
xmlns:xmi="http://www.omg.org/spec/XMI/20110701"
 version="2.0">
 <xsl:strip-space elements="*"/> 
<xsl:output indent="yes" method="xml"/>        
 <xsl:template match="@*|node()"> 
<xsl:copy> 
<xsl:apply-templates select="@*|node()"/> 
</xsl:copy> 
</xsl:template> 
<xsl:template match="node"> 
<xsl:apply-templates select="node()"/>
 </xsl:template>
</xsl:stylesheet>

我现在没有想法如何实现这一目标。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

这是一个示例XSLT 2.0样式表,主要工作不是复制命名空间(默认情况下是这样),主要工作是从extra1(和潜在的后代)中删除命名空间,我这样做不同模式:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:namespace1="http://namespace" xmlns:xmi="http://www.omg.org/spec/XMI/20110701"
  exclude-result-prefixes="namespace1 xmi">

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

<xsl:template match="/">
  <xsl:apply-templates select="xmi:XMI/mode/node1"/>
  <xsl:apply-templates select="xmi:XMI/extra1" mode="strip-namespaces"/>
</xsl:template>

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

<xsl:template match="node()" mode="strip-namespaces">
  <xsl:element name="{local-name()}">
    <xsl:apply-templates select="@*"/>
    <xsl:apply-templates mode="strip-namespaces"/>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>

输入为

<?xml version="1.0" encoding="UTF-8"?>
<xmi:XMI xmlns:namespace1="http://namespace" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" attribute1="some1">

<mode>
<node0>0</node0>

<node1 attribute2="some2"> 
    <child1 name="a" id="1"/>
    <child2 name="b" id="2"/>
</node1>

</mode>

<extra1 id="1"/>
<extra2 id="3"/>

</xmi:XMI>

Saxon 9.4的输出是

<?xml version="1.0" encoding="UTF-8"?><node1 xmlns:namespace1="http://namespace" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" attribute2="some2" attribute1="some1">
    <child1 name="a" id="1"/>
    <child2 name="b" id="2"/>
</node1><extra1 id="1"/>

答案 1 :(得分:0)

该脚本工作表示感谢。但今天我的任务改变了一点:( 对不起,第一个问题不是最终要求:(

现在我需要做类似的事情:

1)节点可以使用命名空间,我现在不知道节点的位置, 可以是namespace1:mode / node0 / namespace1:parm,但可以是namespace1:mode / node0 /../ namespace1:parm 或namespace1:mode / node0 /../ element或类似但需要按类型和名称查找节点, 其中namespace1:type =“type1”和name =“givenName”

2)可能是不同的节点需要成为根节点,例如namespace1:parm或element,但必须每次都有标签namespace1:parm。 首先,我需要不删除xmi节点,如果有使用的节点则不需要合并属性。

3)命名空间每次都可以不同,现在不用如何使这项工作。需要删除未使用的标签。

4)可能需要另一个转换,但是当xmi:XMI和namespace1:parm格式化标签在xmi:XMI标签中没有extar标签时,需要将xmi:XMI与namespace1:parm合并并保留所有属性和命名空间。

输入:

<?xml version="1.0" encoding="UTF-8"?>
<xmi:XMI xmlns:namespace1="http://namespace" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" attribute1="some1" xmlns:M="mOptions" xmlns:N="nOptions">

 <namespace1:mode name="Main">
 <node0>0</node0>

<namespace1:parm name="node1" attribute2="some2" namespace1:type="type1"> 
    <child1 name="a" id="1"/>
    <child2 name="b" id="2"/>
</namespace1:parm>

<element name="node2" attribute2="some3" namespace1:type="type2"> 
    <child6 name="a6" id="6"/>
    <child7 name="b7" id="7"/>
</element>

<node id="55"/>

</namespace1:mode>

<M:extra1 id="1"/>
<M:extra2 id="2"/>
<M:extra6 id="6"/>
<M:extra7 id="7"/>

</xmi:XMI>

我需要与上次相似的第一个可能性,需要找到名称空间的所有内容。试图修改xsl,没有成功。 需要的输出: 当namespace1:type =“type1”

<?xml version="1.0" encoding="UTF-8"?>

<namespace1:parm name="node1" attribute2="some2" namespace1:type="type1"> 
        <child1 name="a" id="1"/>
        <child2 name="b" id="2"/>
</namespace1:parm>

<M:extra1 id="1"/>
<M:extra2 id="2"/>

当namespace1:type =“type2”

<?xml version="1.0" encoding="UTF-8"?>
<xmi:XMI xmlns:namespace1="http://namespace" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" attribute1="some1" xmlns:M="mOptions" xmlns:N="nOptions">

<namespace1:parm name="node2" attribute2="some3" namespace1:type="type2"> 
        <child6 name="a6" id="6"/>
    <child7 name="b7" id="7"/>
</namespace1:parm>

<M:extra6 id="6"/>
<M:extra7 id="7"/>
</xmi:XMI>

如果:          

<namespace1:parm name="node2" attribute2="some3" namespace1:type="type2"> 
        <child6 name="a6" id="6"/>
    <child7 name="b7" id="7"/>
</namespace1:parm>
</xmi:XMI> 

然后需要

<?xml version="1.0" encoding="UTF-8"?>  
<namespace1:parm name="node2" attribute2="some3" namespace1:type="type2"xmlns:namespace1="http://namespace" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" attribute1="some1" xmlns:M="mOptions" xmlns:N="nOptions"> 
        <child6 name="a6" id="6"/>
    <child7 name="b7" id="7"/>
</namespace1:parm>

试过:

       <xsl:template match="*">
    <xsl:copy>
        <xsl:for-each select="@*">
            <xsl:attribute name="{name(.)}">
                <xsl:value-of select="."/>
            </xsl:attribute>
        </xsl:for-each>
        <xsl:apply-templates select="xmi:XMI|*[@namespace1:type='type1']"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="xmi:XMI|*[@namespace1:type='type1']">
    <xsl:copy>
        <xsl:for-each select="@*">
            <xsl:attribute name="{name(.)}">
                <xsl:value-of select="."/>
            </xsl:attribute>
        </xsl:for-each>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

但是得到:

             <?xml version="1.0" encoding="UTF-8"?>
  <xmi:XMI xmlns:namespace1="http://namespace"
             xmlns:xmi="http://www.omg.org/spec/XMI/20110701"
             xmlns:M="mOptions"
           xmlns:N="nOptions"
           attribute1="some1">some1<namespace1:mode name="Main">
        <namespace1:parm name="node1" attribute2="some2"           namespace1:type="type1">node1some2type1<child1 name="a" id="1"/>
           <child2 name="b" id="2"/>
        </namespace1:parm>
     </namespace1:mode>
     <M:extra1 id="1"/>
       <M:extra2 id="3"/>
     <M:extra6 id="6"/>
     <M:extra7 id="7"/>
     </xmi:XMI>