使用xslt删除根元素
我有一个xml模式,其结构如下使用xslt删除根元素,xslt,Xslt,我有一个xml模式,其结构如下 <Level> <Level1>...data...</Level1> <Level2>...data...</Level2> . . . </Level> …数据。。。 …数据。。。 . . . 我想删除标记。在xslt的帮助下,我应该如何做到这一点。对于任何“如何保持大部分XML不变,但对其中的一小部分进行调整”的问题,标准答案是“使用一个标识模板,然后为您想要更改的特定内容覆盖它”
<Level>
<Level1>...data...</Level1>
<Level2>...data...</Level2>
.
.
.
</Level>
…数据。。。
…数据。。。
.
.
.
我想删除
标记。在xslt的帮助下,我应该如何做到这一点。对于任何“如何保持大部分XML不变,但对其中的一小部分进行调整”的问题,标准答案是“使用一个标识模板,然后为您想要更改的特定内容覆盖它”
但正如李斯特先生在评论中指出的那样,这将给您留下一些格式不好的XML,因为它将有多个文档元素
当我将此样式表应用于输入XML时
<Level>
<Level1>...data...</Level1>
<Level2>...data...</Level2>
</Level>
…数据。。。
…数据。。。
它产生了结果
<Level1>...data...</Level1>
<Level2>...data...</Level2>
…数据。。。
…数据。。。
如果要将文档元素的所有子元素存储在变量中,可以执行以下操作:
<xsl:variable name="myVar" select="/*/*"/>
但是,如果希望样式表生成字符串,这可能是一个解决方案:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:apply-templates select="node()"/>
</xsl:template>
<xsl:template match="*">
<!-- We write the opening tag -->
<xsl:value-of select="concat('<',local-name())"/>
<!-- Now, all attributes -->
<xsl:apply-templates select="@*"/>
<!-- Depending on whether we have an empty element or not,
we're adding the content or closing it immediately -->
<xsl:choose>
<xsl:when test="node()">
<!-- Close opening tag -->
<xsl:value-of select="'>'"/>
<!-- Add the content -->
<xsl:apply-templates select="node()"/>
<!-- Write closing tag -->
<xsl:value-of select="concat('</',local-name(),'>')"/>
</xsl:when>
<xsl:otherwise>
<!-- Create empty element by closing tag immediately -->
<xsl:value-of select="'/>'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="@*">
<!-- Write an attribute -->
<xsl:value-of select="concat(' ',local-name(),'="',.,'"')"/>
</xsl:template>
</xsl:stylesheet>
它会生成文本(因此您不会得到格式不正确的XML)。它有点过于简化,因为它不处理名称空间、注释、处理指令和属性中的引号。如果您的输入XML包含其中任何一个,您就必须优化样式表。我已经创建了一个新的XSLT定义,它在代码的帮助下满足了我的要求
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" method="text" omit-xml-declaration="yes"/>
<xsl:variable name="nl">
<xsl:text/>
</xsl:variable>
<xsl:variable name="tb">
<xsl:text/>
</xsl:variable>
<xsl:template match="/*">
<!-- Open the root array -->
<xsl:text>[{</xsl:text>
<xsl:value-of select="$nl"/>
<!-- Process all the child nodes of the root -->
<xsl:apply-templates mode="detect" select="*">
<xsl:with-param name="indent" select="$tb"/>
</xsl:apply-templates>
<!-- Close the root array -->
<xsl:value-of select="$nl"/>
<xsl:text>}]</xsl:text>
</xsl:template>
<xsl:template match="*" mode="detect">
<xsl:choose>
<xsl:when test="name(preceding-sibling::*[1]) = name(current()) and name(following-sibling::*[1]) != name(current())">
<xsl:apply-templates mode="obj-content" select="."/>
<xsl:text>]</xsl:text>
<xsl:if test="count(following-sibling::*[name() != name(current())]) > 0">, </xsl:if>
</xsl:when>
<xsl:when test="name(preceding-sibling::*[1]) = name(current())">
<xsl:apply-templates mode="obj-content" select="."/>
<xsl:if test="name(following-sibling::*) = name(current())">, </xsl:if>
</xsl:when>
<xsl:when test="following-sibling::*[1][name() = name(current())]">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>" : [</xsl:text>
<xsl:apply-templates mode="obj-content" select="."/>
<xsl:text>, </xsl:text>
</xsl:when>
<xsl:when test="count(./child::*) > 0 or count(@*) > 0">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>" : [<xsl:apply-templates
mode="obj-content" select="."/>
<xsl:if test="count(following-sibling::*) > 0">], </xsl:if>
</xsl:when>
<xsl:when test="count(./child::*) = 0">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>" : "<xsl:apply-templates select="."/>
<xsl:text>"</xsl:text>
<xsl:if test="count(following-sibling::*) > 0">, </xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="obj-content">
<xsl:text>{</xsl:text>
<xsl:apply-templates mode="attr" select="@*"/>
<xsl:if test="count(@*) > 0 and (count(child::*) > 0 or text())">, </xsl:if>
<xsl:apply-templates mode="detect" select="./*"/>
<xsl:if test="count(child::*) = 0 and text() and not(@*)">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>" : "<xsl:value-of select="text()"/>
<xsl:text>"</xsl:text>
</xsl:if>
<xsl:if test="count(child::*) = 0 and text() and @*">
<xsl:text>: "</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>"</xsl:text>
</xsl:if>
<xsl:text>}</xsl:text>
<xsl:if test="position() < last()">, </xsl:if>
</xsl:template>
<xsl:template match="@*" mode="attr">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>" : "<xsl:value-of select="."/>
<xsl:text>"</xsl:text>
<xsl:if test="position() < last()">,</xsl:if>
</xsl:template>
<xsl:template match="node/@TEXT | text()" name="removeBreaks">
<xsl:param name="pText" select="normalize-space(.)"/>
<xsl:choose>
<xsl:when test="not(contains($pText, '
'))">
<xsl:copy-of select="$pText"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(substring-before($pText, '
'), ' ')"/>
<xsl:call-template name="removeBreaks">
<xsl:with-param name="pText" select="substring-after($pText, '
')"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
[{
}]
]
,
,
"
" : [
,
"
" : [
],
"
" : "
"
,
{
,
"
" : "
"
: "
"
}
,
"
" : "
"
,
然后剩下两个根级别的元素;这就是您想要的吗?我希望结构像…数据…数据…您确定要这样吗?在无效的XML中有多个根元素。@freefaller…是的,我确定我想要这样。此外,所有级别项,即级别1、2等,都需要分配给一个非有效的变量无界…这也可以通过xslt实现吗?@user1980193请澄清“分配给非无界变量”的含义。XSLT通常会生成XML。它不会将任何内容分配给XSLT之外的变量。我正在尝试一种转换,其中目标将是字符串变量,该转换将保存所有Level1、2等元素。因此,您需要一个值为“…data…data…”的字符串变量?@user1980193这听起来好像超出了XSLT转换本身的范围,而是与您从其他代码调用XSLT的方式有关。例如,如果您在Java中使用
javax.xml.transform
,您可以转换为写入StringWriter
的StreamResult
。
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" method="text" omit-xml-declaration="yes"/>
<xsl:variable name="nl">
<xsl:text/>
</xsl:variable>
<xsl:variable name="tb">
<xsl:text/>
</xsl:variable>
<xsl:template match="/*">
<!-- Open the root array -->
<xsl:text>[{</xsl:text>
<xsl:value-of select="$nl"/>
<!-- Process all the child nodes of the root -->
<xsl:apply-templates mode="detect" select="*">
<xsl:with-param name="indent" select="$tb"/>
</xsl:apply-templates>
<!-- Close the root array -->
<xsl:value-of select="$nl"/>
<xsl:text>}]</xsl:text>
</xsl:template>
<xsl:template match="*" mode="detect">
<xsl:choose>
<xsl:when test="name(preceding-sibling::*[1]) = name(current()) and name(following-sibling::*[1]) != name(current())">
<xsl:apply-templates mode="obj-content" select="."/>
<xsl:text>]</xsl:text>
<xsl:if test="count(following-sibling::*[name() != name(current())]) > 0">, </xsl:if>
</xsl:when>
<xsl:when test="name(preceding-sibling::*[1]) = name(current())">
<xsl:apply-templates mode="obj-content" select="."/>
<xsl:if test="name(following-sibling::*) = name(current())">, </xsl:if>
</xsl:when>
<xsl:when test="following-sibling::*[1][name() = name(current())]">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>" : [</xsl:text>
<xsl:apply-templates mode="obj-content" select="."/>
<xsl:text>, </xsl:text>
</xsl:when>
<xsl:when test="count(./child::*) > 0 or count(@*) > 0">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>" : [<xsl:apply-templates
mode="obj-content" select="."/>
<xsl:if test="count(following-sibling::*) > 0">], </xsl:if>
</xsl:when>
<xsl:when test="count(./child::*) = 0">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>" : "<xsl:apply-templates select="."/>
<xsl:text>"</xsl:text>
<xsl:if test="count(following-sibling::*) > 0">, </xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="obj-content">
<xsl:text>{</xsl:text>
<xsl:apply-templates mode="attr" select="@*"/>
<xsl:if test="count(@*) > 0 and (count(child::*) > 0 or text())">, </xsl:if>
<xsl:apply-templates mode="detect" select="./*"/>
<xsl:if test="count(child::*) = 0 and text() and not(@*)">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>" : "<xsl:value-of select="text()"/>
<xsl:text>"</xsl:text>
</xsl:if>
<xsl:if test="count(child::*) = 0 and text() and @*">
<xsl:text>: "</xsl:text>
<xsl:value-of select="text()"/>
<xsl:text>"</xsl:text>
</xsl:if>
<xsl:text>}</xsl:text>
<xsl:if test="position() < last()">, </xsl:if>
</xsl:template>
<xsl:template match="@*" mode="attr">
<xsl:text>"</xsl:text>
<xsl:value-of select="name()"/>" : "<xsl:value-of select="."/>
<xsl:text>"</xsl:text>
<xsl:if test="position() < last()">,</xsl:if>
</xsl:template>
<xsl:template match="node/@TEXT | text()" name="removeBreaks">
<xsl:param name="pText" select="normalize-space(.)"/>
<xsl:choose>
<xsl:when test="not(contains($pText, '
'))">
<xsl:copy-of select="$pText"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(substring-before($pText, '
'), ' ')"/>
<xsl:call-template name="removeBreaks">
<xsl:with-param name="pText" select="substring-after($pText, '
')"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>