如何消除重复的XML命名空间定义?

如何消除重复的XML命名空间定义?,xml,namespaces,xml-namespaces,Xml,Namespaces,Xml Namespaces,我经常遇到XML,其中同一名称空间被多次定义,而不是仅在需要它的元素的父元素处定义 是否有一种简单的方法/工具可以提取XML中的所有名称空间定义,并将这些定义中的每一个重新定位到一个节点,以便每个名称空间只定义一次?最好还有一个选项,让所有节点都以其名称空间作为前缀(而不是使用某个父节点的默认名称空间)。我发现这将产生更具可读性的XML 举个例子,如何自动翻译 <m:Albums xmlns:m="http://www.example.com/music"> <m:Albu

我经常遇到XML,其中同一名称空间被多次定义,而不是仅在需要它的元素的父元素处定义

是否有一种简单的方法/工具可以提取XML中的所有名称空间定义,并将这些定义中的每一个重新定位到一个节点,以便每个名称空间只定义一次?最好还有一个选项,让所有节点都以其名称空间作为前缀(而不是使用某个父节点的默认名称空间)。我发现这将产生更具可读性的XML

举个例子,如何自动翻译

<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=“…”
,其中属性的值取决于相应元素范围内的前缀)?