【问题标题】:Copy xml namespace and attributes to other node using xslt使用 xslt 将 xml 命名空间和属性复制到其他节点
【发布时间】:2012-05-29 14:34:39
【问题描述】:

所以我是 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>

我现在不知道如何做到这一点。任何帮助表示赞赏。

【问题讨论】:

  • 你确定你想要一个没有根元素的片段作为结果吗?这是可能的,但不寻常,所以让我们先确认一下。而且我不认为发布的示例命名空间格式良好的 XML 因为根元素具有前缀 xmi 但没有该前缀的命名空间声明,因此很难说出您想要实现的目标。
  • 对不起,错过了 xmi 命名空间。是的,我现在删除根节点是不寻常的,但对于这项任务,我需要它。可能需要一个 xslt 转换来保留 xmi:XMI 节点并删除除 node1 和 extra1 之外的其他节点,但认为简单的 xsl 修改会有所帮助(编辑到主帖)。
  • 如果节点像 和使用命名空间 从 xml 文件中提取该节点有什么区别吗?

标签: xml xslt xslt-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"/>

【讨论】:

    【解决方案2】:

    该脚本有效,谢谢。但是今天我的任务发生了一些变化:( 抱歉,第一个问题不是最终要求:(

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

    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 标记中只有 xmi:XMI 和 namespace1:parm 格式的标记且没有 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"/>
    

    当命名空间1: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>
    

    【讨论】:

    • 我知道我的第一个问题是不正确的,但我现在卡住了,无法弄清楚:(如果有人能提供帮助,我将非常感激。或者至少给出如何解决这个问题的提示。当我尝试修改 没有成功。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    • 2020-01-24
    • 2021-05-20
    • 1970-01-01
    相关资源
    最近更新 更多