XSLT-删除根节点和第一个子节点,并将grand-child作为根节点



需要以下逻辑方面的帮助。

源XML--

<?xml version="1.0" encoding="UTF-8"?>
<multimap:Messages xmlns:multimap="http://somenamespace.com/xi/XI/SplitAndMerge">
<multimap:Message1>
<ns0:ToBeRoot xmlns:ns0="http://mynamespace.com">
<ns0:children_level1 xmlns:ns0="http://mynamespace.com">
<Somedata/>
</ns0:children_level1>
</ns0:ToBeRoot>
<ns0:ToBeRoot xmlns:ns0="http://mynamespace.com">
<ns0:children_level2 xmlns:ns0="http://mynamespace.com">
<Somedata/>
</ns0:children_level2>
</ns0:ToBeRoot>
</multimap:Message1>
</multimap:Messages>

目标XML(必需(

<?xml version="1.0" encoding="UTF-8"?>
<ns0:ToBeRoot xmlns:ns0="http://mynamespace.com">
<ns0:children_level1 xmlns:ns0="http://mynamespace.com">
<Somedata/>
</ns0:children_level1>
<ns0:children_level2 xmlns:ns0="http://mynamespace.com">
<Somedata/>
</ns0:children_level2>
</ns0:ToBeRoot>

XSLT我试过了,

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://somenamespace.com/xi/XI/SplitAndMerge">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<!-- template for the document element -->
<xsl:template match="/*">
<xsl:apply-templates select="node()/node()/node()"/>
</xsl:template>
<xsl:template match="ToBeRoot">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

我认为需要在模板中添加一些内容<xsl:template-match="ToBeRoot">但是正在挣扎,请帮帮我。

使用上述XSLT 的输出

<?xml version="1.0" encoding="UTF-8"?>
<ns0:children_level1 xmlns:ns0="http://mynamespace.com" xmlns:multimap="http://somenamespace.com/xi/XI/SplitAndMerge">
<Somedata/>
</ns0:children_level1>

<ns0:children_level2 xmlns:ns0="http://mynamespace.com" xmlns:multimap="http://somenamespace.com/xi/XI/SplitAndMerge">
<Somedata/>
</ns0:children_level2>

最简单的方法是:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/*">
<ns0:ToBeRoot xmlns:ns0="http://mynamespace.com">
<xsl:copy-of select="*/*/*"/>
</ns0:ToBeRoot>
</xsl:template>
</xsl:stylesheet>

这在复制的元素上留下了一个冗余的命名空间声明,这应该是无害的。如果你想删除它,那么你必须重新创建元素,而不是复制它们:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/*">
<ns0:ToBeRoot xmlns:ns0="http://mynamespace.com">
<xsl:apply-templates select="*/*/*"/>
</ns0:ToBeRoot>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

或者,如果您的处理器支持它:

XSLT 2.0

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/*">
<ns0:ToBeRoot xmlns:ns0="http://mynamespace.com">
<xsl:copy-of select="*/*/*" copy-namespaces="no"/>
</ns0:ToBeRoot>
</xsl:template>
</xsl:stylesheet>

添加:

从有效载荷中动态获取名称ns0:ToBeRoot是否可行

是。代替:

<ns0:ToBeRoot xmlns:ns0="http://mynamespace.com">
<!-- ... -->
</ns0:ToBeRoot>

用途:

<xsl:element name="{name(*/*[1])}" namespace="{namespace-uri(*/*[1])}">
<!-- ... -->
</xsl:element>

听起来好像你想要

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://mynamespace.com"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="*/*/ns0:ToBeRoot[1]"/>
</xsl:template>

<xsl:template match="ns0:ToBeRoot">
<xsl:copy>
<xsl:apply-templates select="node() | following-sibling::ns0:ToBeRoot/node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

或者更好的XSLT2或3:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://mynamespace.com"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="*/*/ns0:ToBeRoot[1]"/>
</xsl:template>

<xsl:template match="ns0:ToBeRoot">
<xsl:copy copy-namespaces="no">
<xsl:apply-templates select="node() | following-sibling::ns0:ToBeRoot/node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

您的命名空间声明中出现了一些混乱:xmlns:ns0是";http://mynamespace.com"在您的XML中;http://somenamespace.com/xi/XI/SplitAndMerge"在XSLT中。

同步它们将得到以下XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://mynamespace.com" xmlns:multimap="http://somenamespace.com/xi/XI/SplitAndMerge">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

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

<!-- template for the document element -->
<xsl:template match="/multimap:Messages">
<xsl:element name="ns0:ToBeRoot" namespace="http://mynamespace.com">
<xsl:apply-templates select="multimap:Message1/ns0:ToBeRoot/ns0:*" /> 
</xsl:element>
</xsl:template>
</xsl:stylesheet>

它会给你想要的输出:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:ToBeRoot xmlns:ns0="http://mynamespace.com">
<ns0:children_level1>
<Somedata/>
</ns0:children_level1>
<ns0:children_level2>
<Somedata/>
</ns0:children_level2>
</ns0:ToBeRoot>

最新更新