代码之家  ›  专栏  ›  技术社区  ›  Acewave

如何用前缀替换xmlns命名空间属性?

  •  2
  • Acewave  · 技术社区  · 9 年前

    我一直在尝试用C语言编写一个实用程序,它接受一个XML文件,从标记中删除xmlns属性,在根标记中设置这些属性的前缀,然后在标记中使用这些前缀。

    <?xml version="1.0" encoding="utf-8"?>
    <Main version="1.0" xmlns="urn:root:v1">
        <Report>
            <Title>Some Value</Title>
        </Report>
        <Content>
            <Address>
                <CountryName xmlns="urn:location:v2">Australia</CountryName>
            </Address>
        </Content>
    </Main>
    

    目标XML文件:

    <?xml version="1.0" encoding="utf-8"?>
    <root:Main version="1.0" xmlns:root="urn:root:v1" xmlns:loc="urn:location:v2">
        <root:Report>
            <root:Title>Some Value</root:Title>
        </root:Report>
        <root:Content>
            <root:Address>
                <loc:CountryName>Australia</loc:CountryName>
            </root:Address>
        </root:Content>
    </root:Main>
    

    我已经通过以下代码实现了部分功能。我用根前缀替换了所有没有属性的标记,并将xmlns属性添加到根标记中,但没有成功地从CountryName标记中删除xmlns属性并在那里使用前缀。

    XDocument doc = XDocument.Load(@"C:\Temp\Source.xml");
    
    var content = XElement.Parse(doc.ToString());
    
    content.Attributes("xmlns").Remove();
    
    content.Add(new XAttribute(XNamespace.Xmlns + "root", "urn:root:v1"));
    content.Add(new XAttribute(XNamespace.Xmlns + "loc", "urn:location:v2"));
    
    foreach (var node in doc.Root.Descendants().Where(n => n.Name.NamespaceName == "urn:location:v2"))
    {
        node.Attribute("xmlns").Remove();
        node.Add(new XAttribute(XNamespace.Xmlns + "loc", "urn:location:v2"));
    }   
    
    content.Save(@"C:\Temp\Target.xml");
    

    任何帮助都将不胜感激-谢谢!

    2 回复  |  直到 9 年前
        1
  •  1
  •   Charles Mager    9 年前

    你不在一百万英里之外。您所需要做的就是删除任何现有的命名空间声明属性,然后将想要的属性添加到根中。剩下的会处理好的。

    var doc = XDocument.Load(@"C:\Temp\Source.xml");
    
    doc.Descendants().Attributes().Where(x => x.IsNamespaceDeclaration).Remove();
    doc.Root.Add(new XAttribute(XNamespace.Xmlns + "root", "urn:root:v1"));
    doc.Root.Add(new XAttribute(XNamespace.Xmlns + "loc", "urn:location:v2"));
    
    doc.Save(@"C:\Temp\Target.xml");
    

    this fiddle 用于演示。

        2
  •  1
  •   Parfait    9 年前

    考虑 XSLT here 。此外,您选择使用的XSLT处理器必须允许 document() 函数。

    XSLT (另存为.xsl文件;注意标题中声明的命名空间)

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                                  xmlns:root="urn:root:v1" xmlns:local="urn:location:v2">
        <xsl:output omit-xml-declaration="no" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="node()|@*">
           <xsl:copy>
             <xsl:apply-templates select="node()|@*"/>
           </xsl:copy>
        </xsl:template>
    
        <xsl:template match="*">
          <xsl:element name="root:{name()}" namespace="urn:root:v1">
             <xsl:copy-of select="document('')/*/namespace::local"/>
             <xsl:apply-templates select="node()|@*"/>
          </xsl:element>
        </xsl:template>    
    
        <xsl:template match="*[local-name()='CountryName']">
          <xsl:element name="local:{name()}" namespace="urn:location:v2">
             <xsl:apply-templates select="node()|@*"/>
          </xsl:element>
        </xsl:template>
    
    </xsl:stylesheet>
    

    var myXslTrans = new XslCompiledTransform(); 
    
    myXslTrans.Load("XSLTScript.xsl"); 
    myXslTrans.Transform("Input.xml", "Output.xml"); 
    

    XML

    <?xml version="1.0"?>
    <root:Main xmlns:root="urn:root:v1" xmlns:local="urn:location:v2" version="1.0">
      <root:Report>
        <root:Title>Some Value</root:Title>
      </root:Report>
      <root:Content>
        <root:Address>
          <local:CountryName>Australia</local:CountryName>
        </root:Address>
      </root:Content>
    </root:Main>