如何消除重复的XML命名空间定义?
我经常遇到XML,其中同一名称空间被多次定义,而不是仅在需要它的元素的父元素处定义 是否有一种简单的方法/工具可以提取XML中的所有名称空间定义,并将这些定义中的每一个重新定位到一个节点,以便每个名称空间只定义一次?最好还有一个选项,让所有节点都以其名称空间作为前缀(而不是使用某个父节点的默认名称空间)。我发现这将产生更具可读性的XML 举个例子,如何自动翻译如何消除重复的XML命名空间定义?,xml,namespaces,xml-namespaces,Xml,Namespaces,Xml Namespaces,我经常遇到XML,其中同一名称空间被多次定义,而不是仅在需要它的元素的父元素处定义 是否有一种简单的方法/工具可以提取XML中的所有名称空间定义,并将这些定义中的每一个重新定位到一个节点,以便每个名称空间只定义一次?最好还有一个选项,让所有节点都以其名称空间作为前缀(而不是使用某个父节点的默认名称空间)。我发现这将产生更具可读性的XML 举个例子,如何自动翻译 <m:Albums xmlns:m="http://www.example.com/music"> <m:Albu
<m:Albums xmlns:m="http://www.example.com/music">
<m:Album xmlns:m="http://www.example.com/music">
<m:Artist xmlns:m="http://www.example.com/music">
<c:Name xmlns:c="http://www.example.com/common">
Sting
</c:Name>
</m:Artist>
<m:Title>
Mercury Falling
</m:Title>
</m:Album>
<Album xmlns="http://www.example.com/music">
<Artist>
<c:Name xmlns:c="http://www.example.com/common">
Maria Mena
</c:Name>
</Artist>
<Title xmlns="http://www.example.com/music">
Weapon in Mind
</Title>
</Album>
</m:Albums>
刺
汞下降
玛莉亚·梅娜
心中的武器
这件事
<m:Albums xmlns:m="http://www.example.com/music" xmlns:c="http://www.example.com/common">
<m:Album>
<m:Artist>
<c:Name>
Sting
</c:Name>
</m:Artist>
<m:Title>
Mercury Falling
</m:Title>
</m:Album>
<m:Album>
<m:Artist>
<c:Name>
Maria Mena
</c:Name>
</m:Artist>
<m:Title>
Weapon in Mind
</m:Title>
</m:Album>
</m:Albums>
刺
汞下降
玛莉亚·梅娜
心中的武器
作为对我自己问题的部分回答,我发现unix命令
xmllint --nsclean
部分解决了这个问题,但它并没有消除所有重复的名称空间。当应用到问题中的示例XML时,它会产生以下结果
<m:Albums xmlns:m="http://www.example.com/music">
<m:Album>
<m:Artist>
<c:Name xmlns:c="http://www.example.com/common">
Sting
</c:Name>
</m:Artist>
<m:Title>
Mercury Falling
</m:Title>
</m:Album>
<Album xmlns="http://www.example.com/music">
<Artist>
<c:Name xmlns:c="http://www.example.com/common">
Maria Mena
</c:Name>
</Artist>
<Title>
Weapon in Mind
</Title>
</Album>
</m:Albums>
刺
汞下降
玛莉亚·梅娜
心中的武器
这将消除父节点中已声明的名称空间。但是,它不会将重复的命名空间声明拉到公共父级(例如c:Name
节点),也不会通过将受影响的节点转换为使用等效的非默认命名空间(例如默认命名空间中的Album
节点及其子节点)来删除重复的默认命名空间
仍然希望找到一种解决方案,在
xmllint
失败的情况下也可以删除重复的名称空间。作为对我自己问题的更好回答,我偶然发现了一种完全符合我要求的解决方案
使用此XSLT和Saxon转换问题输入XML的结果:
<m:Albums xmlns:m="http://www.example.com/music" xmlns:c="http://www.example.com/common">
<m:Album>
<m:Artist>
<c:Name>
Sting
</c:Name>
</m:Artist>
<m:Title>
Mercury Falling
</m:Title>
</m:Album>
<m:Album>
<m:Artist>
<c:Name>
Maria Mena
</c:Name>
</m:Artist>
<m:Title>
Weapon in Mind
</m:Title>
</m:Album>
</m:Albums>
刺
汞下降
玛莉亚·梅娜
心中的武器
问题在于,作用域内的命名空间声明构成文档信息集的一部分,因此您所寻找的转换实际上改变了文档的语义—您正在更改许多节点的限定名称(尽管不是它们的本地名称或命名空间URI)并在以前不在作用域中的节点上引入新的命名空间绑定(例如根元素上的c
前缀)。在这种特殊情况下,这没有太大区别,但没有100%通用的方法来做到这一点-您希望如何处理相同前缀在不同位置映射不同的情况?或者对元素名称以外的内容使用前缀映射的文档(例如,xsi:type=“…”
,其中属性的值取决于相应元素范围内的前缀)?