首页 文章

使用XPath - Saxon .net API替换从另一个文档中选择的一个xml文档的节点

提问于
浏览
0

我试图使用相同的XPath替换从另一个文档中选择的节点替换一个文档中的节点 . 我正在使用Saxon XPath选择器从两个文档中选择节点,但我没有找到任何关于如何替换节点的线索 .

假设我的XPath是:/ bookstore / book,以下是我到目前为止从源文档和目标文档访问节点的一段代码 .

Processor SaxonProcessor = new Processor();
XPathCompiler Compiler = SaxonProcessor.NewXPathCompiler();

XmlDocument xmlDocumentTarget = new XmlDocument();
xmlDocumentTarget.LoadXml(targetXml);

DocumentBuilder sBuilder = SaxonProcessor.NewDocumentBuilder();
var sourceNode = sBuilder.Wrap(xmlDocumentSource);

XmlDocument xmlDocumentTarget = new XmlDocument();
xmlDocumentTarget.LoadXml(targetXml);

DocumentBuilder sBuilder = SaxonProcessor.NewDocumentBuilder();
var sourceDoc = sBuilder.Wrap(xmlDocumentSource);

DocumentBuilder tBuilder = SaxonProcessor.NewDocumentBuilder();
var targetDoc = tBuilder.Wrap(xmlDocumentTarget);

string xPath = @"/bookstore/book";
var sourceExp = Compiler.Compile(xPath).Load();
sourceExp.ContextItem = sourceDoc;

var targetExp = Compiler.Compile(xPath).Load();
targetExp.ContextItem = targetDoc;

var sourceXdmValue = sourceExp.Evaluate(); // Gives me source nodes
var targetXdmValue = targetExp.Evaluate(); // Gives me target nodes to replace

现在我想从源文档中的节点替换目标文档中的节点 . 我怎么能用Saxon API做到这一点?

请注意,在目标文档中,不包含带有“my”命名空间的书籍,因为不会根据提供的XPath从源中选择该书籍 .

源XML

<bookstore specialty="novel">
  <book style="autobiography">
    <author>
      <first-name>Joe</first-name>
      <last-name>Bob</last-name>
      <award>Trenton Literary Review Honorable Mention</award>
    </author>
    <price>12</price>
  </book>
  <book style="textbook">
    <author>
      <first-name>Mary</first-name>
      <last-name>Bob</last-name>
      <publication>Selected Short Stories of
        <first-name>Mary</first-name>
        <last-name>Bob</last-name>
      </publication>
    </author>
    <editor>
      <first-name>Britney</first-name>
      <last-name>Bob</last-name>
    </editor>
    <price>55</price>
  </book>
  <book style="novel" id="myfave">
    <author>
      <first-name>Toni</first-name>
      <last-name>Bob</last-name>
      <degree from="Trenton U">B.A.</degree>
      <degree from="Harvard">Ph.D.</degree>
      <award>Pulitzer</award>
      <publication>Still in Trenton</publication>
      <publication>Trenton Forever</publication>
    </author>
    <price intl="Canada" exchange="0.7">6.50</price>
    <excerpt>
      <p>It was a dark and stormy night.</p>
      <p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p>
      <definition-list>
        <term>Trenton</term>
        <definition>misery</definition>
      </definition-list>
    </excerpt>
  </book>
  <my:book xmlns:my="uri:mynamespace" style="leather" price="29.50">
    <my:title>Who's Who in Trenton</my:title>
    <my:author>Robert Bob</my:author>
  </my:book>
</bookstore>

目标XML

<bookstore specialty="novel">
  <book style="History">
    <author>
      <first-name>Joe</first-name>
      <last-name>Bob</last-name>
      <award>Trenton Literary Review Honorable Mention</award>
    </author>
    <price>12</price>
  </book>
</bookstore>

结果XML

<bookstore specialty="novel">
  <book style="autobiography">
    <author>
      <first-name>Joe</first-name>
      <last-name>Bob</last-name>
      <award>Trenton Literary Review Honorable Mention</award>
    </author>
    <price>12</price>
  </book>
  <book style="textbook">
    <author>
      <first-name>Mary</first-name>
      <last-name>Bob</last-name>
      <publication>Selected Short Stories of
        <first-name>Mary</first-name>
        <last-name>Bob</last-name>
      </publication>
    </author>
    <editor>
      <first-name>Britney</first-name>
      <last-name>Bob</last-name>
    </editor>
    <price>55</price>
  </book>
  <book style="novel" id="myfave">
    <author>
      <first-name>Toni</first-name>
      <last-name>Bob</last-name>
      <degree from="Trenton U">B.A.</degree>
      <degree from="Harvard">Ph.D.</degree>
      <award>Pulitzer</award>
      <publication>Still in Trenton</publication>
      <publication>Trenton Forever</publication>
    </author>
    <price intl="Canada" exchange="0.7">6.50</price>
    <excerpt>
      <p>It was a dark and stormy night.</p>
      <p>But then all nights in Trenton seem dark and
      stormy to someone who has gone through what
      <emph>I</emph> have.</p>
      <definition-list>
        <term>Trenton</term>
        <definition>misery</definition>
      </definition-list>
    </excerpt>
  </book>
</bookstore>

2 回答

  • 1

    我不确定你的简单XPath表达式需要Saxon和XPath 2.0,我不确定你是否真的要删除目标中选择的所有元素,然后只是插入源中选择的元素作为 DocumentElement 的子元素但是混合Saxon和.NET的DOM API将是如此

    Processor SaxonProcessor = new Processor();
            XPathCompiler Compiler = SaxonProcessor.NewXPathCompiler();
    
            XmlDocument sourceDomDoc = new XmlDocument();
            sourceDomDoc.Load("../../XMLFile1.xml");
    
            DocumentBuilder sBuilder = SaxonProcessor.NewDocumentBuilder();
            XdmNode sourceNode = sBuilder.Wrap(sourceDomDoc);
    
            XmlDocument targetDomDoc = new XmlDocument();
            targetDomDoc.Load("../../XMLFile2.xml");
    
            XdmNode targetNode = sBuilder.Wrap(targetDomDoc);
    
    
    
            string xPath = @"/bookstore/book";
            var sourceExp = Compiler.Compile(xPath).Load();
            sourceExp.ContextItem = sourceNode;
    
            var targetExp = Compiler.Compile(xPath).Load();
            targetExp.ContextItem = targetNode;
    
            var sourceXdmValue = sourceExp.Evaluate(); // Gives me source nodes
            var targetXdmValue = targetExp.Evaluate(); // Gives me target nodes to replace
            foreach (XdmNode toRemove in targetXdmValue)
            {
                XmlNode domToRemove = toRemove.getUnderlyingXmlNode();
                domToRemove.ParentNode.RemoveChild(domToRemove);
            }
    
            foreach (XdmNode tobeCopied in sourceXdmValue)
            {
                XmlNode copy = targetDomDoc.ImportNode(tobeCopied.getUnderlyingXmlNode(), true);
                targetDomDoc.DocumentElement.AppendChild(copy);
            }
    
            targetDomDoc.Save(Console.Out); // for debugging
    

    但是,我同意在XSLT 2.0中这样做似乎是更好的方法,因为你已经使用了Saxon .

  • 0

    基本答案是“解包”XPath表达式返回的XdmNode值以获取底层DOM节点,然后使用DOM接口修改底层的XmlDocument实例 . 所以你根本就没有使用Saxon API .

    但就个人而言,我会以不同的方式解决这个问题:我会在XSLT转换中完成整个过程 .

    我担心我不能给你实际代码,因为我不理解你的逻辑 . 为什么结果文档包含“源”中的所有书籍和杂志元素,而不包括my:book元素,而“目标”中没有任何内容?

相关问题