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

时间:2015-01-07 14:23:41

标签: xml namespaces xml-namespaces

我经常遇到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>

2 个答案:

答案 0 :(得分:0)

作为我自己问题的部分答案,我发现了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节点),也不会通过将受影响的节点转换为使用等效的非默认命名空间来删除​​重复的默认命名空间(例如{默认命名空间中的{1}}节点及其子节点。

仍然希望在Album失败的情况下也能删除重复名称空间的解决方案。

答案 1 :(得分:0)

作为我自己问题的更好答案,我偶然发现了this external XSLT transformation,这正是我想要的。

使用此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>