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

时间:2016-03-02 14:16:30

标签: c# xml

我有以下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>

3 个答案:

答案 0 :(得分: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);
        }
    }
}

答案 1 :(得分:1)

您可以使用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文件。

答案 2 :(得分:0)

感谢您的帮助,我设法用

解决了这个问题
 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;
      }
 }