xml - XSLT - 重命名具有特定属性的所有子元素
问题描述
我有以下 XML 文档
<root>
<List1 array="true">
<Item>
<Value1>405</Value1>
<Value2>Text</Value2>
<List2 array="true">
<Item>123</Item>
<Item>345</Item>
</List2>
<List3 array="true">
<Item>
<Value1>a</Value1>
<Value2>b</Value2>
</Item>
</List3>
<Value3>21956CB</Value3>
</Item>
</List1>
</root>
我想将<Item>
具有array
属性的元素的所有子元素重命名为父元素的名称。目标 XML 应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<List1 array="true"/>
<List1>
<Value1>405</Value1>
<Value2>Text</Value2>
<List2 array="true"/>
<List2>123</List2>
<List2>345</List2>
<List3 array="true"/>
<List3>
<Value1>a</Value1>
<Value2>b</Value2>
</List3>
<Value3>21956CB</Value3>
</List1>
</root>
我的 XSLT 仅适用于第一个元素的 Items <List1>
。<List2>
and将<List3>
被忽略,以便我的 XSLTis 的结果:
错误的结果:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<List1 array="true"/>
<List1>
<Value1>405</Value1>
<Value2>Text</Value2>
<List2 array="true">
<Item>123</Item>
<Item>345</Item>
</List2>
<List3 array="true">
<Item>
<Value1>a</Value1>
<Value2>b</Value2>
</Item>
</List3>
<Value3>21956CB</Value3>
</List1>
</root>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" media-type="text/xml" method="xml"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//*[@array]">
<xsl:if test="count(./Item) = 1">
<xsl:element name="{name(.)}">
<xsl:attribute name="array">true</xsl:attribute>
</xsl:element>
</xsl:if>
<xsl:for-each select="./Item">
<xsl:element name="{name(..)}">
<xsl:choose>
<!-- is the current node just a text without child then use just the text -->
<xsl:when test="count(./*) = 0">
<xsl:copy-of select="text()"/>
</xsl:when>
<!-- otherwise copy all childs except the null values -->
<xsl:otherwise>
<xsl:copy-of select="./*"/>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
我的 XSLT 有什么问题?我的 XSLT 知识不太好,我认为我遗漏了一些明显的东西。
我希望你能帮助我。
解决方案
请尝试以下 XSLT 2.0 样式表
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" version="2.0">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[@array]/Item">
<xsl:variable name="name" select="parent::*/name(.)"/>
<xsl:element name="{$name}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
它使用 Saxon HE/PE/EE 9.9.1.7 进行了测试。这是一个解释:
首先使用身份模板将输入原封不动地复制到输出中。
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
然后将所有<Item>
具有父元素的元素与@array
属性匹配,获取父元素的名称,并在新元素中使用该名称。
<xsl:template match="*[@array]/Item">
<xsl:variable name="name" select="parent::*/name(.)"/>
<xsl:element name="{$name}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
推荐阅读
- swift - 在swift 5中创建一个mysql连接函数
- javascript - JavaScript。将生成的单选按钮从写入到 HTML 从循环更改为不同类型的输入
- jquery - 外部文件中的 jQuery 似乎不起作用
- ios - 如何在地图上显示多个注释?
- vim - 如何更改 python vim 模块中行号的内容?
- spring-boot - Spring Boot 容器在另一个容器中找不到 kafka 代理
- python - Python,使用简单循环获取数组的最大值
- html - 如何将下拉 div 的宽度设置为与其按钮相同
- android - BottomNavigationView 的标题颜色为渐变
- excel - 具有动态行的 Countif 函数