XSLT:复制元素及其周围的元素(递归循环错误)
XSLT: Copy Element with its surrounding Elements (Recursive Loop Error)
我正在努力寻找这个问题的解决方案,因为我最终陷入了递归循环。
XML 来源示例:
<runtime xmlns="http://xxx/v1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="xxx.xsd">
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>Body</body>
</message>
</messages>
我需要将 Messages 元素放在 body 元素中
<runtime xmlns="http://xxx/v1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="xxx.xsd">
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>Body</body>
</message>
</messages>
</body>
</message>
</messages>
我无法在不陷入循环错误的情况下提出可行的解决方案。任何帮助都适用。
这是您可以查看的一种方式:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:v1="http://xxx/v1">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="v1:body">
<xsl:copy>
<xsl:copy-of select="../.."/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
作为智力练习,在 XSLT 2.0 中,您可以:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://xxx/v1">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- identity transform -->
<xsl:template match="@*|node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body">
<xsl:copy>
<xsl:apply-templates select="../.." mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body" mode="copy">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
您必须 运行 复制模板,但 <body>
元素除外。对于这个特殊标签,制作另一个带有名称的复制模板以从新开始驱动转换,并使用另一个路径来避免循环。
主体的经典复制模板执行
<xsl:template match="node()[local-name()!='body'] | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
对于正文元素,通过指定另一条路径(带模式)从头开始复制
<xsl:template match="*[local-name()='body']">
<xsl:copy>
<xsl:apply-templates select="/*:runtime/*:messages" mode='embedded'/>
</xsl:copy>
</xsl:template>
并使用另一个复制模板将标签复制到 body 元素中
<xsl:template match="node() | @*" mode="embedded">
<xsl:copy>
<xsl:apply-templates select="node() | @*" mode="embedded"/>
</xsl:copy>
</xsl:template>
结果:
<?xml version="1.0" encoding="UTF-8"?>
<runtime xmlns="http://xxx/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="xxx.xsd">
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>Body</body>
</message>
</messages>
</body>
</message>
</messages>
</runtime>
我正在努力寻找这个问题的解决方案,因为我最终陷入了递归循环。
XML 来源示例:
<runtime xmlns="http://xxx/v1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="xxx.xsd">
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>Body</body>
</message>
</messages>
我需要将 Messages 元素放在 body 元素中
<runtime xmlns="http://xxx/v1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="xxx.xsd">
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>Body</body>
</message>
</messages>
</body>
</message>
</messages>
我无法在不陷入循环错误的情况下提出可行的解决方案。任何帮助都适用。
这是您可以查看的一种方式:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:v1="http://xxx/v1">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="v1:body">
<xsl:copy>
<xsl:copy-of select="../.."/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
作为智力练习,在 XSLT 2.0 中,您可以:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://xxx/v1">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- identity transform -->
<xsl:template match="@*|node()" mode="#all">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body">
<xsl:copy>
<xsl:apply-templates select="../.." mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="body" mode="copy">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
您必须 运行 复制模板,但 <body>
元素除外。对于这个特殊标签,制作另一个带有名称的复制模板以从新开始驱动转换,并使用另一个路径来避免循环。
主体的经典复制模板执行
<xsl:template match="node()[local-name()!='body'] | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
对于正文元素,通过指定另一条路径(带模式)从头开始复制
<xsl:template match="*[local-name()='body']">
<xsl:copy>
<xsl:apply-templates select="/*:runtime/*:messages" mode='embedded'/>
</xsl:copy>
</xsl:template>
并使用另一个复制模板将标签复制到 body 元素中
<xsl:template match="node() | @*" mode="embedded">
<xsl:copy>
<xsl:apply-templates select="node() | @*" mode="embedded"/>
</xsl:copy>
</xsl:template>
结果:
<?xml version="1.0" encoding="UTF-8"?>
<runtime xmlns="http://xxx/v1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="xxx.xsd">
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>
<messages>
<message>
<severity>debug</severity>
<source>Client</source>
<subject>Subject</subject>
<body>Body</body>
</message>
</messages>
</body>
</message>
</messages>
</runtime>