2013-11-19 2 views
0

У меня есть 287 отчетов SSRS (файлы XML), где мне нужно добавить параметр.
Все они начинаются так:Как избежать добавления xmlns = "" в XML-элементе?

<?xml version="1.0" encoding="utf-8"?> 
<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner"> 
<DataSources> 
<DataSource Name="COR_Basic"> 
<rd:DataSourceID>addde073-f37c-4b59-ae3a-25231ffc0ec6</rd:DataSourceID> 
<DataSourceReference>COR_Basic</DataSourceReference> 
</DataSource> 
</DataSources> 
<InteractiveHeight>29.7cm</InteractiveHeight> 
<ReportParameters> 
<ReportParameter Name="in_report_name"> 
<DataType>String</DataType> 
<DefaultValue> 
<Values> 
<Value>=Globals!ReportName</Value> 
</Values> 
</DefaultValue> 
<Prompt>Report Name</Prompt> 
<Hidden>true</Hidden> 
</ReportParameter> 
<ReportParameter Name="in_mandant"> 
<DataType>String</DataType> 
<DefaultValue> 
<Values> 
<Value>0</Value> 
</Values> 
</DefaultValue> 
<Prompt>in_mandant</Prompt> 
<Hidden>true</Hidden> 
</ReportParameter> 

Теперь я хочу, чтобы автоматически добавить параметр «PROC» для всех отчетов.
Что означает, что нужно вставить этот бит XML

<ReportParameter Name="proc"> 
<DataType>String</DataType> 
<DefaultValue> 
<Values> 
<Value>MyTestValue</Value> 
</Values> 
</DefaultValue> 
<Prompt>MyPromptText</Prompt> 
<Hidden>true</Hidden> 
</ReportParameter> 

после

<ReportParameter Name="in_mandant"> 
... 
</ReportParameter> 

Это код, который я до сих пор:

public static System.Xml.XmlDocument File2XmlDocument(string strFileName) 
{ 
    // http://blogs.msdn.com/b/tolong/archive/2007/11/15/read-write-xml-in-memory-stream.aspx 
    System.Xml.XmlDocument doc = new System.Xml.XmlDocument(); 
    // doc.Load(memorystream); 
    // doc.Load(FILE_NAME); 

    using (System.Xml.XmlTextReader xtrReader = new System.Xml.XmlTextReader(strFileName)) 
    { 

     doc.Load(xtrReader); 
     xtrReader.Close(); 
    } // End Using xtrReader 

    return doc; 
} // End Function File2XmlDocument 




     public static System.Xml.XmlNamespaceManager GetReportNamespaceManager(System.Xml.XmlDocument doc) 
     { 
      System.Xml.XmlNamespaceManager nsmgr = new System.Xml.XmlNamespaceManager(doc.NameTable); 
      nsmgr.AddNamespace("dft", "http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition"); 

      return nsmgr; 
     } // End Function GetReportNamespaceManager 



public static void AddProc(string strFilename) 
     { 
      System.Xml.XmlDocument doc = File2XmlDocument(strFilename); 
      System.Xml.XmlElement root = doc.DocumentElement; 
      System.Xml.XmlNamespaceManager nsmgr = GetReportNamespaceManager(doc); 

      System.Xml.XmlNode xnMandant = root.SelectSingleNode("/dft:Report/dft:ReportParameters/dft:ReportParameter[@Name=\"in_mandant\"]", nsmgr); 

      string strReportName = System.IO.Path.GetFileNameWithoutExtension(strFilename); 

      if (xnMandant != null) 
      { 
       LogMessage("{0}\t{1}", strReportName, xnMandant.FirstChild.Value); 

       string frag = @"<ReportParameter Name=""proc""> 
<DataType>String</DataType> 
<DefaultValue> 
<Values> 
<Value>MyTestValue</Value> 
</Values> 
</DefaultValue> 
<Prompt>MyPromptText</Prompt> 
<Hidden>true</Hidden> 
</ReportParameter>"; 

       System.Xml.XmlDocumentFragment xmlDocFrag = doc.CreateDocumentFragment(); 
       xmlDocFrag.InnerXml = frag; 

       System.Xml.XmlNode xn = xnMandant.ParentNode.InsertAfter(xmlDocFrag, xnMandant); 

       Console.WriteLine(xn.OuterXml); 

      } 
      else 
       LogMessage("{0}\tKein Parameter in_mandant", strReportName); 


      SaveDocument(doc, strFilename); 
     } // End Sub PrintStichtag 

Это вставляет XML-фрагмент в в правильном месте, но у меня есть xmlns="" после "proc".

<ReportParameter Name="proc" xmlns=""> 
<DataType>String</DataType> 
<DefaultValue> 
<Values> 
<Value>MyTestValue</Value> 
</Values> 
</DefaultValue> 
<Prompt>MyPromptText</Prompt> 
<Hidden>true</Hidden> 
</ReportParameter> 

Как я могу избежать пустого атрибута xmlns?
(За исключением загрузки XML-файла в виде текста и выполнения string.replace).

ответ

1

Похоже, что это не возможно все («спасибо» читать единственное свойство).
Единственный способ сделать это заменой в OuterXml документа и перезагрузкой документа.

public static void SaveDocument(System.Xml.XmlDocument doc, string strFilename, bool bDoReplace) 
    { 
     string strSavePath = GetSavePath(); 
     strSavePath = System.IO.Path.Combine(strSavePath, System.IO.Path.GetFileName(strFilename)); 

     if (bDoReplace) 
     { 
      doc.LoadXml(doc.OuterXml.Replace("xmlns=\"\"", "")); 
      // doc.LoadXml(doc.OuterXml.Replace(strTextToReplace, strReplacementText)); 
     } 

     using (System.Xml.XmlTextWriter xtw = new System.Xml.XmlTextWriter(strSavePath, System.Text.Encoding.UTF8)) 
     { 
      xtw.Formatting = System.Xml.Formatting.Indented; // if you want it indented 
      xtw.Indentation = 4; 
      xtw.IndentChar = ' '; 

      doc.Save(xtw); 
     } // End Using xtw 

    } // End Sub SaveDocument 
2

Как я могу избежать пустого атрибута xmlns?

Создайте элементы в правом пространстве имен. Из-за namespace defaulting, все ваши элементы должны быть в пространстве имен http://schemas.microsoft.com/sqlserver/reporting/2005/01/reportdefinition.

Вы можете попробовать вставить фрагмент и , затем установить его значение InnerXml - возможно, это применит пространство имен по умолчанию.

Лично, однако, я бы использовал LINQ to XML, который значительно упрощает обработку пространства имен, а затем конструирует элементы программно, а не анализирует их из текста. Фактически, я бы построил элементы программно в любом случае, а не устанавливал InnerXml - это упростит контроль над такими вещами, как пространства имен, поскольку вы можете указать их при создании элементов.

(я бы также настоятельно рекомендую использовать using директивы, чтобы избежать кода быть приправлен полностью уточненными именами во всем мире.)

+0

Но xmlDocFrag.NamespaceURI только для чтения, я не могу присвоить значение ... –

+0

@Quandary: Крысы, не заметил этого. В этом случае вы можете * попробовать * добавить его перед установкой фрагмента InnerXml, но, честно говоря, вам было бы лучше создавать его программно. –

+0

Это тоже не работает. Но все равно спасибо. Я не могу использовать LINQ btw, мы все еще на .NET 2.0 ... –

1

При добавлении используйте это пространство имен со следующими настройками.

 XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); 
    namespaces.Add(string.Empty, string.Empty); 
Смежные вопросы