在c#中使用带有默认名称空间的Xpath进行规范化

本文关键字:空间 Xpath 规范化 行规 默认 | 更新日期: 2023-09-27 18:04:19

我试图将C14N转换应用于一些生成的XML。看来我不能使用LINQ来检索节点来执行规范化,所以我必须用DOM去"老派",但我认为我正在与默认命名空间发生冲突。

下面是我的代码示例。

static void Main(string[] args)
{
    XmlDocument xDoc = new XmlDocument();
    // Load some test xml
    string path = @"..'..'TestFiles'Test_1.xml";
    if (File.Exists(path) == true)
    { 
        xDoc.PreserveWhitespace = true;
        using (FileStream fs = new FileStream(path, FileMode.Open))
        {
            xDoc.Load(fs);
        }
    }
    //Instantiate an XmlNamespaceManager object. 
    System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(xDoc.NameTable);
    //Add the namespaces used in books.xml to the XmlNamespaceManager.
    xmlnsManager.AddNamespace("", "http://www.myApps.co.uk/");
    // Create a list of nodes to have the Canonical treatment
        //Execute the XPath query using the SelectNodes method of the XmlDocument.
        //Supply the XmlNamespaceManager as the nsmgr parameter.
        //The matching nodes will be returned as an XmlNodeList.
    XmlNodeList nodeList = xDoc.SelectNodes("/ApplicationsBatch/Applications|/ApplicationsBatch/Applications//*", xmlnsManager);
    // Perform the C14N transform on the data
    XmlDsigC14NTransform transform = new XmlDsigC14NTransform();
    transform.LoadInput(nodeList);
    MemoryStream ms = (MemoryStream)transform.GetOutput(typeof(Stream));
    File.WriteAllBytes(@"..'..'TestFiles'ModifiedTest_1", ms.ToArray());
}

And my XML:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ApplicationsBatch xmlns="http://www.myApps.co.uk/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <MessageHeader>
    <MessageID>00000003</MessageID>
    <Body>11223344556</Body>
    <Timestamp>2011-08-02T09:00:00</Timestamp>
    <MessageCheck>?</MessageCheck>
  </MessageHeader>
  <Applications>
    <Application>
      <ApplicantDetails>
        <Title>MR</Title>
        <Forename>HOMER</Forename>
        <Middlenames>
          <Middlename></Middlename>
        </Middlenames>
        <PresentSurname>SIMPSON</PresentSurname>
        <CurrentAddress>
          <Address>
            <AddressLine1>ADDRESS LINE1</AddressLine1>
            <AddressLine2>ADDRESS LINE2</AddressLine2>
            <AddressTown>ADDRESS Town</AddressTown>
            <AddressCounty>COUNTY</AddressCounty>
            <Postcode>POST CODE</Postcode>
            <CountryCode>GB</CountryCode>
          </Address>
          <ResidentFromGyearMonth>2007-01</ResidentFromGyearMonth>
        </CurrentAddress>
      </ApplicantDetails>
    </Application>
    <Application>
      <ApplicantDetails>
        <Title>MR</Title>
        <Forename>BART</Forename>
        <Middlenames>
          <Middlename></Middlename>
        </Middlenames>
        <PresentSurname>SIMPSON</PresentSurname>
        <CurrentAddress>
          <Address>
            <AddressLine1>ADDRESS LINE1</AddressLine1>
            <AddressLine2>ADDRESS LINE2</AddressLine2>
            <AddressTown>ADDRESS Town</AddressTown>
            <AddressCounty>COUNTY</AddressCounty>
            <Postcode>POST CODE</Postcode>
            <CountryCode>GB</CountryCode>
          </Address>
          <ResidentFromGyearMonth>2007-01</ResidentFromGyearMonth>
        </CurrentAddress>
      </ApplicantDetails>
    </Application>
  </Applications>
</ApplicationsBatch>

我已经阅读了该地区的其他一些主题,并遇到了这个宝石,但它并没有解决问题。

使用XPath Visualiser显示应该选择所需的节点,但我的代码未能选择任何节点。

在c#中使用带有默认名称空间的Xpath进行规范化

我找到了我问题的部分答案。

当一个新的命名空间被添加到管理器时,默认的命名空间似乎不能是一个空字符串。这就是我最后的结果:

//Instantiate an XmlNamespaceManager object. 
System.Xml.XmlNamespaceManager xmlnsManager = new System.Xml.XmlNamespaceManager(xDoc.NameTable);
//Add the namespaces used to the XmlNamespaceManager.
xmlnsManager.AddNamespace("x", "http://www.myApps.co.uk/");

然后我需要修改XPath以反映名称空间标识符,如下所示:

// Create a list of nodes to have the Canonical treatment
    //Execute the XPath query using the SelectNodes method of the XmlDocument.
    //Supply the XmlNamespaceManager as the nsmgr parameter.
    //The matching nodes will be returned as an XmlNodeList.
XmlNodeList nodeList = xDoc.SelectNodes("/x:ApplicationsBatch/x:Applications|/x:ApplicationsBatch/x:Applications//*", xmlnsManager);

节点现在被选中并准备进行转换…虽然返回正确的XML结构,但所有的值都被删除了,但这是另一个问题的问题。