Можете ли вы отфильтровать XML-документ по подмножеству узлов, используя XPath в C #?

2

Я пытаюсь отфильтровать документ Xml таким образом в подмножество себя, используя XPath.

Я использовал XPath для получения XmlNodeList, но мне нужно преобразовать это в XML-документ.

Есть ли способ преобразовать XMLNodeList в XmlDocument или создать XmlDocument, напрямую связав другой XmlDocument?

Теги:

3 ответа

4
Лучший ответ

С XmlDocument вам нужно будет импортировать эти узлы во второй документ;

    XmlDocument doc = new XmlDocument();
    XmlElement root = (XmlElement)doc.AppendChild(doc.CreateElement("root"));
    XmlNodeList list = // your query
    foreach (XmlElement child in list)
    {
        root.AppendChild(doc.ImportNode(child, true));
    }
  • 0
    В конце концов, это ответ, с которым я пошел.
1

Это довольно типичная причина использования XSLT, который является эффективным и мощным инструментом для преобразования одного документа XML в другой (или в HTML или текст).

Здесь минимальная программа для выполнения преобразования XSLT и отправки результатов на консоль:

using System;
using System.Xml;
using System.Xml.Xsl;

namespace XsltTest
{
    class Program
    {
        static void Main(string[] args)
        {
            XslCompiledTransform xslt = new XslCompiledTransform();
            xslt.Load("test.xslt");

            XmlWriter xw = XmlWriter.Create(Console.Out);
            xslt.Transform("input.xml", xw);
            xw.Flush();
            xw.Close();

            Console.ReadKey();
        }
    }
}

Здесь фактический XSLT, который сохраняется в test.xslt в каталоге программы. Это довольно просто: с учетом входного документа, элемент верхнего уровня которого называется input, он создает элемент output и копируется над каждым дочерним элементом, для атрибута value установлено значение true.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>

    <xsl:template match="/input">
      <output>
        <xsl:apply-templates select="*[@value='true']"/>
      </output>
    </xsl:template>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

И здесь input.xml:

<?xml version="1.0" encoding="utf-8" ?>
<input>
  <element value="true">
    <p>This will get copied to the output.</p>
    <p>Note that the use of the identity transform means that all of this content
    gets copied to the output simply because templates were applied to the 
    <em>element</em> element.
  </p>
  </element>
  <element value="false">
    <p>This, on the other hand, won't get copied to the output.</p>
  </element>
</input>
  • 0
    Это было бы, но я фильтрую динамически, поэтому я не знаю заранее, к чему мне это нужно отфильтровать. +1 за XSLT, что довольно круто.
  • 0
    Существует множество способов динамической фильтрации с помощью XSLT. Вы можете передавать аргументы в преобразование; эти аргументы могут содержать критерии фильтрации, которые ваше преобразование считывает и применяет.
0

Я действительно подумал о том, как это сделать, но это не кажется очень элегантным.

используйте StringBuilder для объединения OuterXml каждого из XmlNodes в XmlNodeList...

Как я сказал, это неэлегантно, но я думаю, что это может сработать. Я был бы признателен за любое другое предложение...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню