将所有子兄弟姐妹转换为类父节点
Transform all child siblings into parent-like node
需要将所有子元素转换为父级节点,使它们具有相同的层级和名称。生成的新元素必须包含子元素的所有属性并保留父元素的属性。
来源XML
<?xml version="1.0" encoding="UTF-8"?>
<entry>
<line id="001" att1="aaa" att2="bbb" att3="ccc"/>
<line id="002" att1="ddd" att2="eee" att3="fff"/>
<line id="003" att1="ggg" att2="hhh" att3="iii">
<subline x="name" z="lastname"/>
<subline x="name2" z="lastname2"/>
<underline a="bar" b="foo"/>
</line>
</entry>
期望输出
<entry>
<line id="001" att1="aaa" att2="bbb" att3="ccc"/> <!-- with or without empty x and z attributes' values-->
<line id="002" att1="ddd" att2="eee" att3="fff"/> <!-- with or without empty x and z values-->
<line id="003" att1="ggg" att2="hhh" att3="iii" x="name" z="lastname"/>
<line id="003" att1="ggg" att2="hhh" att3="iii" x="name2" z="lastname2"/>
<line id="003" att1="ggg" att2="hhh" att3="iii" a="bar" b="foo"/>
</entry>
当前的 XSLT 代码
当前代码只匹配第一个子元素。
其他的我都想改造
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="line">
<line>
<xsl:copy-of select="@*"/>
<xsl:attribute name="x">
<xsl:value-of select="subline/@x"/>
</xsl:attribute>
<xsl:attribute name="z">
<xsl:value-of select="subline/@z"/>
</xsl:attribute>
<xsl:apply-templates select="node()"/>
</line>
</xsl:template>
<!-- ===== delete child elements ====== -->
<xsl:template match="subline"/>
<xsl:template match="underline"/>
<!-- ===== [identity] ====== -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- ==== [identity \ ] ====== -->
</xsl:stylesheet>
补充说明(可能有用):所有的属性名都是预先知道的
我建议这样处理:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="line[*]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="line/*">
<line>
<xsl:copy-of select="../@* | @*"/>
</line>
</xsl:template>
</xsl:stylesheet>
需要将所有子元素转换为父级节点,使它们具有相同的层级和名称。生成的新元素必须包含子元素的所有属性并保留父元素的属性。
来源XML
<?xml version="1.0" encoding="UTF-8"?>
<entry>
<line id="001" att1="aaa" att2="bbb" att3="ccc"/>
<line id="002" att1="ddd" att2="eee" att3="fff"/>
<line id="003" att1="ggg" att2="hhh" att3="iii">
<subline x="name" z="lastname"/>
<subline x="name2" z="lastname2"/>
<underline a="bar" b="foo"/>
</line>
</entry>
期望输出
<entry>
<line id="001" att1="aaa" att2="bbb" att3="ccc"/> <!-- with or without empty x and z attributes' values-->
<line id="002" att1="ddd" att2="eee" att3="fff"/> <!-- with or without empty x and z values-->
<line id="003" att1="ggg" att2="hhh" att3="iii" x="name" z="lastname"/>
<line id="003" att1="ggg" att2="hhh" att3="iii" x="name2" z="lastname2"/>
<line id="003" att1="ggg" att2="hhh" att3="iii" a="bar" b="foo"/>
</entry>
当前的 XSLT 代码
当前代码只匹配第一个子元素。 其他的我都想改造
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="line">
<line>
<xsl:copy-of select="@*"/>
<xsl:attribute name="x">
<xsl:value-of select="subline/@x"/>
</xsl:attribute>
<xsl:attribute name="z">
<xsl:value-of select="subline/@z"/>
</xsl:attribute>
<xsl:apply-templates select="node()"/>
</line>
</xsl:template>
<!-- ===== delete child elements ====== -->
<xsl:template match="subline"/>
<xsl:template match="underline"/>
<!-- ===== [identity] ====== -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- ==== [identity \ ] ====== -->
</xsl:stylesheet>
补充说明(可能有用):所有的属性名都是预先知道的
我建议这样处理:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="line[*]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="line/*">
<line>
<xsl:copy-of select="../@* | @*"/>
</line>
</xsl:template>
</xsl:stylesheet>