XSL:删除命名空间,然后转换元素



我有这样的XML:input.xml

<?xml version="1.0" encoding="UTF-8"?>
<somens:Root xmlns:somens="http://url/of/some/namespace">
<somens:Child>
<somens:String>some value here</somens:String>
<somens:Integer>123456</somens:Integer>
<somens:Date>1990-01-01 00:00:00</somens:Date>
<somens:Element>
<somens:name>foo</somens:name>
<somens:value>foo</somens:value>
</somens:Element>
<somens:Element>
<somens:name>foo</somens:name>
<somens:value>bar</somens:value>
</somens:Element>
<somens:Element>
<somens:name>bar</somens:name>
<somens:value>bar</somens:value>
</somens:Element>
</somens:Child>
</somens:Root>

然后应该:

  • 删除所有命名空间
  • 转换<Element><name>foo</name><value>foo</value></Element><Element><name>foo</name><value>bar</value></Element><Element><foo>foo</foo><foo>bar</foo></Element>

output.xml

<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Child>
<String>some value here</String>
<Integer>123456</Integer>
<Date>1990-01-01 00:00:00</Date>
<Element>
<foo>foo</foo>
<foo>bar</foo>
<bar>bar</bar>
</Element>
</Child>
</Root>

我可以像这样使用 xslt 删除命名空间:

<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="*">
<!-- remove element prefix -->
<xsl:element name="{local-name()}">
<!-- process attributes -->
<xsl:for-each select="@*">
<!-- remove attribute prefix -->
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

然后用这个 xslt 转换Element

<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="//Element">
<xsl:element name="{./name}">
<xsl:value-of select="./value"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

并得到这样的 xml:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
<Child>
<String>some value here</String>
<Integer>123456</Integer>
<Date>1990-01-01 00:00:00</Date>
<foo>foo</foo>
<foo>bar</foo>
<bar>bar</bar>
</Child>
</Root>

但我不明白我怎么能:

  1. 使用单个 XSLT 进行所有转换

  2. 从所有Element中切下孩子,并将它们涂抹成单Element

您可以使用单个 XSLT 样式表获取问题中显示的结果,如下所示:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:somens="http://url/of/some/namespace"
exclude-result-prefixes="somens">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- move all elements to no-namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="somens:Child">
<Child>
<xsl:apply-templates select="*[not(self::somens:Element)]"/>
<Element>
<xsl:apply-templates select="somens:Element"/>
</Element>
</Child>
</xsl:template>
<xsl:template match="somens:Element">
<xsl:element name="{somens:name}">
<xsl:value-of select="somens:value"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

找到解决方案!

谢谢 @michael.hor257k

transform.xsl

<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:strip-space elements="*"/>
<!-- move all elements to no-namespace -->
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[*[local-name()='Element']]">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="*[not(local-name()='Element')]"/>
<Element>
<xsl:apply-templates select="*[local-name()='Element']"/>
</Element>
</xsl:element>
</xsl:template>
<xsl:template match="*[local-name()='Element']">
<xsl:element name="{*[local-name()='name']}">
<xsl:value-of select="*[local-name()='value']"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>

相关内容

最新更新