【问题标题】:XML fix namespace declarationXML 修复命名空间声明
【发布时间】:2011-01-27 11:40:25
【问题描述】:

我正在尝试检测/解决 RSS 元素中的 this 错误。 这意味着我必须找到错误的命名空间声明并更改它 值到正确的命名空间。例如:

xmlns:media="http://search.yahoo.com/mrss" 

必须是:

xmlns:media="http://search.yahoo.com/mrss/" 

在给定 org.w3c.Document 的情况下,我该如何实现?

我想知道如何获取某个命名空间的所有元素:

        XPathFactory xpf = XPathFactory.newInstance();
        XPath xpath = xpf.newXPath();
        XPathExpression expr = xpath.compile("//*[namespace-uri()='http://search.yahoo.com/mrss']");


        Object result = expr.evaluate(d, XPathConstants.NODESET);
        if (result != null) {
            NodeList nodes = (NodeList) result;
            for(int node=0;node<nodes.getLength();node++)
            {
                Node n = nodes.item(node);
                this.log.warn("Found old mediaRSS namespace declaration: "+n.getTextContent());
            }

        } 

所以现在我必须弄清楚如何通过 JAXP 更改节点的命名空间。

【问题讨论】:

    标签: java xml rss namespaces mediarss


    【解决方案1】:

    您可能可以使用 XSLT 做到这一点,使用如下规则:

    <xsl:template match="media:*">
       <xsl:element name="local-name()" namespace="http://search.yahoo.com/mrss/">
          <xsl:apply-templates match="node()|@*"/>
       </xsl:element>
    </xsl:template>
    

    媒体绑定到“http://search.yahoo.com/mrss”。

    您可能需要稍微调整语法,因为我是在没有编译器帮助的情况下编写的。此外,您将获得的可能不是非常好的格式(许多元素上的命名空间声明),但它应该是本地正确的。

    【讨论】:

    • 感谢您的回复。但是我正在对象级别访问文档。我也不确定本地前缀是否总是“媒体:”。毕竟这是其他人制作的 RSS-Feed。上帝知道他们使用什么前缀:-/
    • 他们不必这样做!您可以在 XSLT 中使用任何前缀(例如“x:*”),重要的是命名空间。 (换句话说,您在 XSLT 中使用的前缀与 XML 文件中的前缀没有任何关系。)
    • @er4z0r - 您在 XSLT(即媒体)中声明的命名空间前缀不必与源文档中的命名空间前缀匹配。只要它们都引用相同的 URI,模板就会匹配。
    • 只是看看,如果我说对了。您的 XSLT 会查找所有以表示“错误”命名空间的前缀为前缀的元素,然后将这些元素的命名空间直接设置为正确的命名空间?
    • 是的,没错。您还可以尝试匹配“xmlns”属性并更改它们(如果您愿意,可以获得更好的 XML)。但除此之外,您无论如何都必须更改元素。
    【解决方案2】:

    为了完整起见:

    Java 代码:

    Document d = out.outputW3CDom(converted);
                DOMSource oldDocument = new DOMSource(d);
                DOMResult newDocument = new DOMResult();
                TransformerFactory tf = TransformerFactory.newInstance();
                StreamSource xsltsource = new StreamSource(
                        getStream(MEDIA_RSS_TRANSFORM_XSL));
                Transformer transformer = tf.newTransformer(xsltsource);
                transformer.transform(oldDocument, newDocument);
    
    private InputStream getStream(String fileName) {
        InputStream xslStream = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("/" + fileName);
        if (xslStream == null) {
            xslStream = Thread.currentThread().getContextClassLoader()      .getResourceAsStream(fileName);
            }
            return xslStream;
        }
    

    样式表:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <!--identity transform that will copy matched node/attribute to the output and apply templates for it's children and attached attributes-->
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="@*|*|text()" />
            </xsl:copy>
        </xsl:template>
    
        <!--Specialized template to match on elements with the incorrect namespace and generate a new element-->
        <xsl:template match="//*[namespace-uri()='http://search.yahoo.com/mrss']">
            <xsl:element name="{local-name()}" namespace="http://search.yahoo.com/mrss/" >
                <xsl:apply-templates select="@*|*|text()" />
            </xsl:element>
        </xsl:template>
    </xsl:stylesheet>
    

    特别感谢 Mads Hansen 为 XSLT 提供了help

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 2019-03-25
      • 1970-01-01
      • 2015-11-25
      • 2012-05-13
      相关资源
      最近更新 更多