Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
141 views
in Technique[技术] by (71.8m points)

c# - How can I prevent appendChild() from adding the xmlns=""

Here is a snippet of my code.

FilterText = HttpUtility.UrlDecode(FilterTxt.Value.ToString());
               XmlWriterSettings settings = new XmlWriterSettings();
               settings.Indent = true;
               TextWriter tw = new StreamWriter("D:\FilterTest.rdl");
               tw.WriteLine(FilterText);
               tw.Close();
               XmlDocument reportrdl = new XmlDocument();
               reportrdl.Load(ReportFile);
               NMS = reportrdl.NamespaceURI;
               XmlNodeList fieldsnode = reportrdl.GetElementsByTagName("DataSet");
               //XmlElement xoo = reportrdl.CreateElement("Filters", NMS);
               //reportrdl.AppendChild(xoo);
               foreach (XmlNode fields in fieldsnode)
               {
                   // second document to merge (the new Filter File)

                   XmlDocument filterrdl = new XmlDocument();
                   filterrdl.Load("D:\FilterTest.rdl");

                   XmlNode imported = reportrdl.ImportNode(filterrdl.DocumentElement, true);

                   fields.AppendChild(imported);
                   break;
               }
               //XmlNodeList filtersnode = reportrdl.GetElementsByTagName("Filters");
               //foreach (XmlNode filters in filtersnode)
               //{
               //    filters.Attributes.RemoveNamedItem("xmlns");
               // }
               reportrdl.Save("D:\NewFilter.rdl");

Here is snippet of the rdl file:

<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
  <DataSources>
    <DataSource Name="BOSS">
      <rd:DataSourceID>c6a8409e-71a4-4e96-86ad-b300a5b942c3</rd:DataSourceID>
      <ConnectionProperties>
        <DataProvider>SQL</DataProvider>
        <ConnectString>dats a no no</ConnectString>
        <IntegratedSecurity>true</IntegratedSecurity>
      </ConnectionProperties>
    </DataSource>
  </DataSources>

Further on down in this file after <Query>, I need to merge in the <Filters>

Here is that file:

<Filters>
  <Filter>
    <FilterExpression>=Fields!RoleID.Value</FilterExpression>
    <Operator>Equal</Operator>
    <FilterValues>
      <FilterValue>=27</FilterValue>
    </FilterValues>
  </Filter>
</Filters>

ends up <Filters xmlns=""> instead of <Filters>

Thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to show us samples of the XML of the two files you're trying to merge.

What's probably happening is that in the first file, reportrdl, the DataSet elements are under a default namespace declaration other than "". Therefore, every element under them that does not have a namespace prefix and does not override the default namespace declaration will be in the default namespace declared by its ancestor.

But you're importing Filters elements that are not in that namespace, and have no prefix. Therefore, in order to prevent them inheriting a default namespace that does not apply to them, they need to undeclare the default namespace, which is done using xmlns="".

If the above is not the case, please provide samples of the two XML documents, so we're not trying to do surgery in the dark.

If the above is the case, the question back to you is, why do you not want the xmlns="" in the output? It sounds like it's the correct output. But maybe you don't want it because you want the imported Filters element to be in the same namespace as its parent; in that case, you need to change the namespace of imported. Then the namespace declarations will follow.

Or maybe you want the imported node to be in no namespace, so the output is technically correct already, but you don't like the aesthetics of xmlns="". Or maybe there's a downstream XML consumer that chokes on xmlns="" for some reason. Tell us more about your constraints so we can know how to help.

Update:

OK, now we know that

  • The elements in the first file are in the reportdefinition namespace, whose URL is "http://schemas.microsoft.com/sqlserver/reporting/2009/01/reportdefinition". We can tell because the top-level element, <Report>, has the default namespace declaration on it: xmlns="http://schemas.microsoft.com.../reportdefinition". This means that for <Report> and all descendants, any element with no namespace prefix is considered to be in the reportdefinition namespace.
  • The elements in the imported file, like <Filters> should be in the same reportdefinition namespace. I infer this from the MS documentation, though it's not clear. Much of this documentation is unfortunately awful ... full of ill-formed XML even!
  • However the imported <Filters> element and descendants are actually in no namespace (before you import them), because they have no namespace prefix and no default namespace declaration.

So when you import the <Filters> element, AppendChild() must act to keep it in the same namespace that it's in (i.e. no namespace) - otherwise, it would be like changing its name. <Filters> in no namespace is a different element from <Filters> in the reportdefinition namespace. If <Filters> were appended under <DataSet> as-is, it would inherit the default namespace declaration from its new ancestor <Report> and thereby its namespace would be changed to the reportdefinition namespace.

However, you do want it to be in the reportdefinition namespace. The easiest way to accomplish that is to change your imported file so that <Filters> is already in that namespace:

<Filters xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition">
  <Filter>

Then, AppendChild() will see that <Filters> is already in the default namespace of its new ancestors, and won't have to undeclare the default namespace. In fact, it can remove the default namespace declaration on <Filters>, which is now redundant.

However, we can't guarantee that it will remove it. One important thing to understand about XML namespaces is that what matters is what namespace each element is in. It doesn't matter what prefix is used to indicate that namespace, nor does it matter where or how many times that namespace prefix (or default namespace) is declared: just so long as each element ends up in the right namespace.

So, whether your imported <Filters> element ends up having a default namespace declaration (DND) or not should not matter to any legitimate XML consumer. All that matters is that it's in the reportdefinition namespace. If a Microsoft RDL processor chokes on the DND, it means that the processor does not adhere to XML namespace standards.

I would really recommend reading a short tutorial on XML namespaces... They're not that complicated, despite their reputation; they're almost ubiquitous when you work with standardized XML vocabularies; and understanding how the declarations work can save you a lot of headache. This one's not short but it's good. I can't recommend the w3schools one because it confuses prefixes with namespaces. :-p

Wow, that got long. I felt like it was necessary, though: we can bail water all day long, but I'd rather plug the leak, which is caused by not understanding how XML namespace declarations work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...