如何从 XML 文档中删除 2 个父命名空间标记

本文关键字:命名空间 删除 XML 文档 | 更新日期: 2023-09-27 18:37:06

>我有以下XML文档,但我需要删除前两个元素(并保留所有子元素)。我似乎无法使用 XPath 执行此操作,因为它们是命名空间?我不太了解XML文档的这一部分,因此也非常欢迎任何解释。此外,HubChangeRequest 是可变的,所以我不能在代码中使用它 - 我需要基本上删除 2 个父元素。

<?xml version="1.0" encoding="UTF-8" standalone="no" ?> 
<mgns1:PlaceXmlMessage xmlns:mgns1="http://www.testing.com/">
    <mgns1:xmlDocument>
        <HubChangeRequest version="1.0">
            <TransactionReference>
                <AuthenticationID>TestSUPPLIERS</AuthenticationID>
                <AuthenticationKey>hidden</AuthenticationKey>
                <TransactionNumber>hidden</TransactionNumber>
            </TransactionReference>
            <MessageNumber>hidden</MessageNumber>
            <MessageCreatedDate>2016-03-01T12:31:31</MessageCreatedDate>
            <ReferenceNumber>ABC123456789</ReferenceNumber>
            <ProductDetails>
                <StockItem LineReference="123456/1">
                    <NewStatus>Despatched</NewStatus>
                    <DespatchReference>3 PARCEL LINE</DespatchReference>
                </StockItem>
                <StockItem LineReference="123345/2">
                    <NewStatus>Despatched</NewStatus>
                    <DespatchReference>3 PARCEL LINE</DespatchReference>
                </StockItem>
            </ProductDetails>
        </HubChangeRequest>
    </mgns1:xmlDocument>
</mgns1:PlaceXmlMessage>

需要明确的是,这就是我想要的结局:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?> 
<HubChangeRequest version="1.0">
    <TransactionReference>
        <AuthenticationID>TestSUPPLIERS</AuthenticationID>
        <AuthenticationKey>hidden</AuthenticationKey>
        <TransactionNumber>hidden</TransactionNumber>
    </TransactionReference>
    <MessageNumber>hidden</MessageNumber>
    <MessageCreatedDate>2016-03-01T12:31:31</MessageCreatedDate>
    <ReferenceNumber>ABC123456789</ReferenceNumber>
    <ProductDetails>
        <StockItem LineReference="123456/1">
            <NewStatus>Despatched</NewStatus>
            <DespatchReference>3 PARCEL LINE</DespatchReference>
        </StockItem>
        <StockItem LineReference="123345/2">
            <NewStatus>Despatched</NewStatus>
            <DespatchReference>3 PARCEL LINE</DespatchReference>
        </StockItem>
    </ProductDetails>
</HubChangeRequest>

如何从 XML 文档中删除 2 个父命名空间标记

试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml =
                "<?xml version='"1.0'" encoding='"UTF-8'" standalone='"no'" ?>" +
                "<mgns1:PlaceXmlMessage xmlns:mgns1='"http://www.testing.com/'">" +
                    "<mgns1:xmlDocument>" +
                        "<HubChangeRequest version='"1.0'">" +
                            "<TransactionReference>" +
                                "<AuthenticationID>TestSUPPLIERS</AuthenticationID>" +
                                "<AuthenticationKey>hidden</AuthenticationKey>" +
                                "<TransactionNumber>hidden</TransactionNumber>" +
                            "</TransactionReference>" +
                            "<MessageNumber>hidden</MessageNumber>" +
                            "<MessageCreatedDate>2016-03-01T12:31:31</MessageCreatedDate>" +
                            "<ReferenceNumber>ABC123456789</ReferenceNumber>" +
                            "<ProductDetails>" +
                                "<StockItem LineReference='"123456/1'">" +
                                    "<NewStatus>Despatched</NewStatus>" +
                                    "<DespatchReference>3 PARCEL LINE</DespatchReference>" +
                                "</StockItem>" +
                                "<StockItem LineReference='"123345/2'">" +
                                    "<NewStatus>Despatched</NewStatus>" +
                                    "<DespatchReference>3 PARCEL LINE</DespatchReference>" +
                                "</StockItem>" +
                            "</ProductDetails>" +
                        "</HubChangeRequest>" +
                    "</mgns1:xmlDocument>" +
                "</mgns1:PlaceXmlMessage>";
            XDocument doc = XDocument.Parse(xml);
            XElement placeXmlMessage = (XElement)doc.FirstNode;
            XElement secondNode = placeXmlMessage.Elements().FirstOrDefault();
            XElement hubChangeRequest = secondNode.Elements().FirstOrDefault();
            placeXmlMessage.ReplaceWith(hubChangeRequest);
        }
    }
}

可以使用 XSLT 转换将输入转换为正确的输出形状。

以下代码将输入 xml(假设它位于 caled input 的字符串变量中)转换为 MemoryStream。

通过 XSLT 将输入转换为流

// Create an XSLT Transformer
var xslt = new XslCompiledTransform();
xslt.Load("copydoc.xslt");
var settings = new XmlWriterSettings
{
    Encoding = new UTF8Encoding(false) // NO BOM
};
// open all streams for reading and writing
using (var ms = new MemoryStream())
{
    using (var xw = XmlWriter.Create(ms, settings))
    {
        // input is the string with the xml input
        using (var sr = new StringReader(input))
        using (var xr = XmlReader.Create(sr))
        {
            xslt.Transform(xr, xw);
            // the memorystream now has the result
        }
    }
    Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}

Copydoc.xslt

Xslt 文件相当简单,它使用两个模板和一个策略应用模板来获取<mgsn1:xmlDocument>节点下的子节点:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
                xmlns:mgns1="http://www.testing.com/"
                exclude-result-prefixes="msxsl mgns1 "
>
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
      <!-- select the child node of xmlDocument-->
      <xsl:apply-templates select="mgns1:PlaceXmlMessage/mgns1:xmlDocument/child::*" />
    </xsl:template>
    <!-- match each element -->
    <xsl:template match="*">
      <!-- make sure to get rid of the namespaces-->
        <xsl:element name="{local-name(.)}">
        <!-- be explicit about copying attributes -->
        <xsl:apply-templates select="@*" />
        <!-- copy childs-->
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>
    <!-- handle attributes -->
    <xsl:template match="@*">
        <xsl:copy/>
    </xsl:template>
</xsl:stylesheet>

如果将文件 copydoc.xslt 添加到项目中,请不要忘记将 projectfile 属性Copy to output directory设置为 copy always否则将找不到 xslt 文件。

感谢您的帮助,我设法解决了这个问题

 xmlDOM.LoadXml(p_strXmlDocument);
 XmlElement root = xmlDOM.DocumentElement;
 XmlNamespaceManager NameSpaceManager = new XmlNamespaceManager(new NameTable());
 NameSpaceManager.AddNamespace("mgns1", "http://www.hidden.com/");
 XmlNodeList nodeList = xmlDOM.SelectNodes("//mgns1:xmlDocument/*", NameSpaceManager);
 string returnStr = "";
 if (nodeList != null)
 {
      foreach (XmlNode node in nodeList)
      {
            returnStr += node.OuterXml;
      }
 }