首页 > 解决方案 > 我正在尝试匹配两个 xml 文件并从第一个文件中获取 xml 节点作为输出 xml

问题描述

我正在尝试编写 ac#.net 应用程序来匹配两个 XML,并获取与第二个 XML 文件匹配的第一个文件中存在的节点。

第一个 XML 包含比模板 XML 文档更多的节点。我正在尝试匹配它们并从源节点获取模板 XML 中存在的节点。下面是示例 XML 文件。

XML 示例文件 1

<document>
<node1>
    <subnode11>
        <subnode111 text="subnode">
        </subnode111>
        <subnode112 text="subnode">
        </subnode112>
    </subnode11>
</node1>
<node2>
    <subnode11>
        <subnode111 text="subnode">
        </subnode111>
        <subnode112 text="subnode">
        </subnode112>
    </subnode11>
</node2>
<node3>
    <subnode11>
        <subnode111 text="subnode">
        </subnode111>
        <subnode112 text="subnode">
        </subnode112>
    </subnode11>
</node3>
<node4>
    <subnode11>
        <subnode111 text="subnode">
        </subnode111>
        <subnode112 text="subnode">
        </subnode112>
    </subnode11>
</node4>
<node5>
    <subnode11>
        <subnode111 text="subnode">
        </subnode111>
        <subnode112 text="subnode">
        </subnode112>
    </subnode11>
</node5>

XML 参考文件 2

<template>
<node2>
    <subnode11>
        <subnode111 text="subnode">
        </subnode111>
        <subnode112 text="subnode">
        </subnode112>
    </subnode11>
</node2>
<node4>
    <subnode11>
        <subnode111 text="subnode">
        </subnode111>
        <subnode112 text="subnode">
        </subnode112>
    </subnode11>
</node4>

所需的输出是

<document>
<node2>
    <subnode11>
        <subnode111 text="subnode">
        </subnode111>
        <subnode112 text="subnode">
        </subnode112>
    </subnode11>
</node2>
<node4>
    <subnode11>
        <subnode111 text="subnode">
        </subnode111>
        <subnode112 text="subnode">
        </subnode112>
    </subnode11>
</node4>

以下是我用 C# 编写的内容。

            if (!string.IsNullOrEmpty(xmlTemplateFilePathLocation))
        {
            string[] filePaths = Directory.GetFiles(xmlTemplateFilePathLocation, "*.xml");
            foreach (string xmlFile in filePaths)
            {
                uniqueFileName = Path.GetFileNameWithoutExtension(xmlFile);
                string xmlContent = File.ReadAllText(xmlFile);
                if (!IsValidXmlString(xmlContent))
                {
                    xmlContent = RemoveInvalidXmlChars(xmlContent);
                }
                if (IsValidXmlString(xmlContent))
                {
                    File.WriteAllText(xmlFile, xmlContent);
                }

                string xsltTextString = string.Empty;

                xsltTextString = xsltTextString + "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:ns=\"some:ns\">";
                xsltTextString = xsltTextString + "<xsl:output omit-xml-declaration=\"yes\" indent=\"yes\"/>";
                xsltTextString = xsltTextString + "<xsl:strip-space elements=\"*\"/>";

                xsltTextString = xsltTextString + "<ns:WhiteList>";

                Dictionary<string, List<int>> nodeTable = new Dictionary<string, List<int>>();
                using (XmlReader reader = XmlReader.Create(xmlFile))
                {
                    while (!reader.EOF)
                    {
                        if (reader.NodeType == XmlNodeType.Element)
                        {
                            if (!nodeTable.ContainsKey(reader.LocalName))
                            {
                                nodeTable.Add(reader.LocalName, new List<int>(new int[] { reader.Depth }));
                            }
                            else if (!nodeTable[reader.LocalName].Contains(reader.Depth))
                            {
                                nodeTable[reader.LocalName].Add(reader.Depth);
                            }
                        }
                        reader.Read();
                    }
                }

                foreach (KeyValuePair<string, List<int>> kv in nodeTable)
                {
                    if (kv.Value.Count == 1 && kv.Value[0] == 1 )
                    {
                        xsltTextString = xsltTextString + "<name>" + kv.Key + "</name>";
                    }

                    for (int i = 0; i < kv.Value.Count; i++)
                    {
                        if (i < kv.Value.Count - 1)
                        {
                            //Console.Write("{0}, ", kv.Value[i]);

                        }
                        else
                        {
                           //Console.WriteLine(kv.Value[i]);
                            xsltTextString = xsltTextString + "<name>" + kv.Value[i] + "</name>";
                        }
                    }
                }
                xsltTextString = xsltTextString + "</ns:WhiteList>";
                xsltTextString = xsltTextString + "<xsl:template match = \"node()|@*\">";
                xsltTextString = xsltTextString + "<xsl:copy>";
                xsltTextString = xsltTextString + "<xsl:apply-templates select = \"node()|@*\"/>";
                xsltTextString = xsltTextString + "</xsl:copy>";
                xsltTextString = xsltTextString + "</xsl:template>";
                xsltTextString = xsltTextString + "<xsl:template match=\"*[not(descendant-or-self::*[name()=document('')/*/ns:WhiteList/*])]\"/>";
                xsltTextString = xsltTextString + "</xsl:stylesheet>";

                //transforming the xml file with the generated XSLT

                StringBuilder htmlOutput = new StringBuilder();
                TextWriter htmlWriter = new StringWriter(htmlOutput);

                File.WriteAllText(xmlTemplateFilePathLocation + uniqueFileName + ".xslt", xsltTextString);

                XslCompiledTransform objXSLTransform = new XslCompiledTransform();

                objXSLTransform.Load(xmlTemplateFilePathLocation + uniqueFileName + ".xslt", new XsltSettings { EnableDocumentFunction = true }, new XmlUrlResolver());

                string xmlFilexml = "C:\\Desktop\\Test\\XML\\722033_1004_2.XML";

                XmlReader readerXML = XmlReader.Create(xmlFilexml);

                objXSLTransform.Transform(readerXML, null, htmlWriter);
                htmlContent = htmlWriter.ToString();

                Console.WriteLine(htmlContent);

使用当前代码,我只能提取主节点而不是子节点。我还需要在输出中获取子节点。

如果父节点匹配,我认为它们是匹配的。Node2 和 Node4 与模板 XML 匹配,并且应该在输出 XML 中与它们的源 XML 的子节点一起出现。

我正在使用 XSLT 1.0,我的最终输出将是 HTML。

提前致谢。

标签: c#xmlcomparexslt-1.0xmldocument

解决方案


推荐阅读