XSLT 2.0 在应用模板后更改 ROOT 的默认命名空间值
XSLT 2.0 changing the default namespace value of ROOT after applying templates
我的目标是能够:
- 将根元素的
xmlns="http://xmlns.example.com/v1"
替换为 xmlns="http://xmlns.example.com"
( 没有 v1)
- 将根元素的
schemaVersion="1"
替换为 schemaVersion="2"
(版本 2)
- 应用其他 模板匹配 以排除(而不是添加)我需要从输入 xml.
中删除的节点
输入xml
<account xmlns="http://xmlns.example.com/v1"
xmlns:ns2="http://xmlns.example/v2"
schemaVersion="1">
<head>Jane Doe</head>
<accountNumber>1234567</accountNumber>
<messageType>CREATE</messageType>
<create>
<ns2:profile>
<ns2:accountNumber>1234567</ns2:accountNumber>
</ns2:profile>
</create>
<ns2:tax>
<ns2:taxExempt>false</ns2:taxExempt>
</ns2:tax>
<contact>
<ns2:address>US</ns2:address>
</contact>
</account>
期望输出xml
<account xmlns="http://xmlns.example.com"
xmlns:ns2="http://xmlns.example/v2"
schemaVersion="2">
<head>Jane Doe</head>
<messageType>ADD</messageType>
<action>A</action>
<ns2:profile>
<ns2:accountNumber>1234567</ns2:accountNumber>
</ns2:profile>
<contact>
<ns2:address>US</ns2:address>
</contact>
</account>
在想要的输出中,我
- 已将根元素第一个命名空间值从
xmlns="http://xmlns.example.com/v1"
更改为 xmlns="http://xmlns.example.com"
(无 v1)
- 已将根元素的
schemaVersion
属性值从 schemaVersion="1"
更改为 schemaVersion="2"
(版本 2)
- 已删除
<accountNumber>
- 已将
<messageType>
值从 CREATE 更改为 ADD
- 已添加
<action>A</action>
- 删除父节点
<create>
但 保留 其子节点。
- 删除了整个
<ns2:tax>
节点及其子节点
我设法产生了所需的输出。但是,它引入了一个问题。
问题:在当前输出中 xml,xmlns="http://xmlns.example.com/v1"
(版本 1) 添加到 <head>
和 <contact>
.
xmlns="http://xmlns.example.com/v1"
该走了.
我的 xsl 的当前输出
<account xmlns="http://xmlns.example.com"
xmlns:ns2="http://xmlns.example/v2"
schemaVersion="2">
<head xmlns="http://xmlns.example.com/v1">Jane Doe</head>
<messageType>ADD</messageType>
<action>A</action>
<ns2:profile>
<ns2:accountNumber>1234567</ns2:accountNumber>
</ns2:profile>
<contact xmlns="http://xmlns.example.com/v1">
<ns2:address>US</ns2:address>
</contact>
</account>
我的 XSL 代码
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://xmlns.example.com/v1"
xmlns:ns2="http://xmlns.example/v2">
<xsl:output method="xml" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<!-- Copy all text nodes, elements and attributes -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- Replace root's xmlns and schemaVersion value -->
<xsl:template match="account">
<account xmlns="http://xmlns.example.com"
xmlns:ns2="http://xmlns.example/v2"
schemaVersion="2">
<xsl:apply-templates />
</account>
</xsl:template>
<!-- remove <accountNumber> -->
<xsl:template match="accountNumber" />
<!-- Change messageType value from CREATE to ADD -->
<!-- Add <action>A</action> -->
<xsl:template
match="account/messageType[text()='CREATE']">
<xsl:element name='messageType'
namespace='http://xmlns.example.com'>
<xsl:value-of select="'ADD'" />
</xsl:element>
<xsl:element name='action'
namespace='http://xmlns.example.com'>
<xsl:value-of select="'A'" />
</xsl:element>
</xsl:template>
<!-- remove node <create> but keep its children -->
<xsl:template match="create">
<xsl:apply-templates />
</xsl:template>
<!-- Removed entire <ns2:tax> node and its children -->
<xsl:template match="ns2:tax" />
<!-- Ensure that the namespace of nodes prefixed with ns2 has "http://xmlns.example/v2" value -->
<xsl:template match="ns2:*">
<xsl:element name="ns2:{local-name()}"
namespace="http://xmlns.example/v2">
<xsl:apply-templates select="@*, node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
我遇到了困难,因为我必须首先将 xpath-default-namespace="http://xmlns.example.com/v1"
设置为版本 1 以匹配我要删除的节点然后我最终需要将 xmlns 值替换为不是版本 1 (xmlns="http://xmlns.example.com/"
)
对于解决此问题的任何建议或想法,我将不胜感激。
谢谢。
如果您想要或需要更改元素的命名空间(并且在某些元素上声明的命名空间适用于其所有后代,因此您需要更改根的命名空间及其所有后代);基于此,我认为您需要编写一个模板作为更改元素命名空间的起点:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://xmlns.example.com"
xmlns:v1="http://xmlns.example.com/v1"
xpath-default-namespace="http://xmlns.example.com/v1"
xmlns:ns2="http://xmlns.example/v2"
exclude-result-prefixes="v1">
<xsl:output method="xml" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/*/@schemaVersion">
<xsl:attribute name="{name()}">2</xsl:attribute>
</xsl:template>
<!-- Change namespace http://xmlns.example.com/v1 to http://xmlns.example.com-->
<xsl:template match="v1:*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="namespace::*[not(. = 'http://xmlns.example.com/v1')]"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<!-- remove <accountNumber> -->
<xsl:template match="accountNumber" />
<!-- Change messageType value from CREATE to ADD -->
<!-- Add <action>A</action> -->
<xsl:template
match="account/mesageType[.='CREATE']">
<messageType>ADD</messageType>
<action>A</action>
</xsl:template>
<!-- remove node <create> but keep its children -->
<xsl:template match="create">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="ns2:*">
<xsl:copy copy-namespaces="no">
<xsl:copy-of select="namespace::*[not(. = 'http://xmlns.example.com/v1')]"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- Removed entire <ns2:tax> node and its children -->
<xsl:template match="ns2:tax" />
</xsl:stylesheet>
我的目标是能够:
- 将根元素的
xmlns="http://xmlns.example.com/v1"
替换为xmlns="http://xmlns.example.com"
( 没有 v1) - 将根元素的
schemaVersion="1"
替换为schemaVersion="2"
(版本 2) - 应用其他 模板匹配 以排除(而不是添加)我需要从输入 xml. 中删除的节点
输入xml
<account xmlns="http://xmlns.example.com/v1"
xmlns:ns2="http://xmlns.example/v2"
schemaVersion="1">
<head>Jane Doe</head>
<accountNumber>1234567</accountNumber>
<messageType>CREATE</messageType>
<create>
<ns2:profile>
<ns2:accountNumber>1234567</ns2:accountNumber>
</ns2:profile>
</create>
<ns2:tax>
<ns2:taxExempt>false</ns2:taxExempt>
</ns2:tax>
<contact>
<ns2:address>US</ns2:address>
</contact>
</account>
期望输出xml
<account xmlns="http://xmlns.example.com"
xmlns:ns2="http://xmlns.example/v2"
schemaVersion="2">
<head>Jane Doe</head>
<messageType>ADD</messageType>
<action>A</action>
<ns2:profile>
<ns2:accountNumber>1234567</ns2:accountNumber>
</ns2:profile>
<contact>
<ns2:address>US</ns2:address>
</contact>
</account>
在想要的输出中,我
- 已将根元素第一个命名空间值从
xmlns="http://xmlns.example.com/v1"
更改为xmlns="http://xmlns.example.com"
(无 v1) - 已将根元素的
schemaVersion
属性值从schemaVersion="1"
更改为schemaVersion="2"
(版本 2) - 已删除
<accountNumber>
- 已将
<messageType>
值从 CREATE 更改为 ADD - 已添加
<action>A</action>
- 删除父节点
<create>
但 保留 其子节点。 - 删除了整个
<ns2:tax>
节点及其子节点
我设法产生了所需的输出。但是,它引入了一个问题。
问题:在当前输出中 xml,xmlns="http://xmlns.example.com/v1"
(版本 1) 添加到 <head>
和 <contact>
.
xmlns="http://xmlns.example.com/v1"
该走了.
我的 xsl 的当前输出
<account xmlns="http://xmlns.example.com"
xmlns:ns2="http://xmlns.example/v2"
schemaVersion="2">
<head xmlns="http://xmlns.example.com/v1">Jane Doe</head>
<messageType>ADD</messageType>
<action>A</action>
<ns2:profile>
<ns2:accountNumber>1234567</ns2:accountNumber>
</ns2:profile>
<contact xmlns="http://xmlns.example.com/v1">
<ns2:address>US</ns2:address>
</contact>
</account>
我的 XSL 代码
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xpath-default-namespace="http://xmlns.example.com/v1"
xmlns:ns2="http://xmlns.example/v2">
<xsl:output method="xml" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<!-- Copy all text nodes, elements and attributes -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- Replace root's xmlns and schemaVersion value -->
<xsl:template match="account">
<account xmlns="http://xmlns.example.com"
xmlns:ns2="http://xmlns.example/v2"
schemaVersion="2">
<xsl:apply-templates />
</account>
</xsl:template>
<!-- remove <accountNumber> -->
<xsl:template match="accountNumber" />
<!-- Change messageType value from CREATE to ADD -->
<!-- Add <action>A</action> -->
<xsl:template
match="account/messageType[text()='CREATE']">
<xsl:element name='messageType'
namespace='http://xmlns.example.com'>
<xsl:value-of select="'ADD'" />
</xsl:element>
<xsl:element name='action'
namespace='http://xmlns.example.com'>
<xsl:value-of select="'A'" />
</xsl:element>
</xsl:template>
<!-- remove node <create> but keep its children -->
<xsl:template match="create">
<xsl:apply-templates />
</xsl:template>
<!-- Removed entire <ns2:tax> node and its children -->
<xsl:template match="ns2:tax" />
<!-- Ensure that the namespace of nodes prefixed with ns2 has "http://xmlns.example/v2" value -->
<xsl:template match="ns2:*">
<xsl:element name="ns2:{local-name()}"
namespace="http://xmlns.example/v2">
<xsl:apply-templates select="@*, node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
我遇到了困难,因为我必须首先将 xpath-default-namespace="http://xmlns.example.com/v1"
设置为版本 1 以匹配我要删除的节点然后我最终需要将 xmlns 值替换为不是版本 1 (xmlns="http://xmlns.example.com/"
)
对于解决此问题的任何建议或想法,我将不胜感激。
谢谢。
如果您想要或需要更改元素的命名空间(并且在某些元素上声明的命名空间适用于其所有后代,因此您需要更改根的命名空间及其所有后代);基于此,我认为您需要编写一个模板作为更改元素命名空间的起点:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://xmlns.example.com"
xmlns:v1="http://xmlns.example.com/v1"
xpath-default-namespace="http://xmlns.example.com/v1"
xmlns:ns2="http://xmlns.example/v2"
exclude-result-prefixes="v1">
<xsl:output method="xml" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/*/@schemaVersion">
<xsl:attribute name="{name()}">2</xsl:attribute>
</xsl:template>
<!-- Change namespace http://xmlns.example.com/v1 to http://xmlns.example.com-->
<xsl:template match="v1:*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="namespace::*[not(. = 'http://xmlns.example.com/v1')]"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:element>
</xsl:template>
<!-- remove <accountNumber> -->
<xsl:template match="accountNumber" />
<!-- Change messageType value from CREATE to ADD -->
<!-- Add <action>A</action> -->
<xsl:template
match="account/mesageType[.='CREATE']">
<messageType>ADD</messageType>
<action>A</action>
</xsl:template>
<!-- remove node <create> but keep its children -->
<xsl:template match="create">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="ns2:*">
<xsl:copy copy-namespaces="no">
<xsl:copy-of select="namespace::*[not(. = 'http://xmlns.example.com/v1')]"/>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!-- Removed entire <ns2:tax> node and its children -->
<xsl:template match="ns2:tax" />
</xsl:stylesheet>