Kam*_*hid 6 .net c# xml xml-parsing
我有一些xml通过一些WCF消息的xmlserialization生成.现在我想制作一个通用的方法,我将提供一个xml文件名和一个前缀mailxml12
.然后在xml文件中,那些名称中没有任何名称空间前缀的元素应替换为mailxml12:
像源文件是:
<DeliveryApptCreateRequest d2p1:ApptType="Pallet" d2p1:PickupOrDelivery="Delivery" d2p1:ShipperApptRequestID="4490660303D5" d2p1:SchedulerCRID="234234" xmlns:d2p1="http://idealliance.org/Specs/mailxml12.0a/mailxml_defs" xmlns="http://idealliance.org/Specs/mailxml12.0a/mailxml_tm">
<SubmittingParty d2p1:MailerID6="123446" d2p1:CRID="342343" d2p1:MaildatUserLicense="A123" />
<SubmittingSoftware d2p1:SoftwareName="asds" d2p1:Vendor="123" d2p1:Version="12" />
<SubmitterTrackingID>2CAD3F71B4405EB16392</SubmitterTrackingID>
<DestinationEntry>No</DestinationEntry>
<OneTimeAppt>
<PreferredAppt>2012-06-29T09:00:00Z</PreferredAppt>
</OneTimeAppt>
<TrailerInfo>
<Trailer>
<TrailerNumber>A</TrailerNumber>
<TrailerLength>20ft</TrailerLength>
</Trailer>
<Carrier>
<CarrierName>N/A</CarrierName>
<URL>http://test.com</URL>
</Carrier>
<BillOfLadingNumber>N/A</BillOfLadingNumber>
</TrailerInfo>
</DeliveryApptCreateRequest>
Run Code Online (Sandbox Code Playgroud)
在所需的方法之后,应将其更改为所有没有前缀的元素名称mailxml:
.就像DeliveryApptCreateRequest
应该成为mailxml:DeliveryApptCreateRequest
元素一样d2p1:CompanyName
应该保持原样.
我试过以下代码
private void RepalceFile(string xmlfile)
{
XmlDocument doc = new XmlDocument();
doc.Load(xmlfile);
var a = doc.CreateAttribute("xmlns:mailxml12tm");
a.Value = "http://idealliance.org/Specs/mailxml12.0a/mailxml_tm";
doc.DocumentElement.Attributes.Append(a);
doc.DocumentElement.Prefix = "mailxml12tm";
foreach (XmlNode item in doc.SelectNodes("//*"))
{
if (item.Prefix.Length == 0)
item.Prefix = "mailxml12tm";
}
doc.Save(xmlfile);
}
Run Code Online (Sandbox Code Playgroud)
唯一的问题是根元素保持原样,而所有根据我的需要进行更改
您可以将整个 XML 解析为字符串,并在适当的位置插入命名空间。然而,该解决方案可以创建大量仅在算法内使用的新字符串,这对性能不利。不过,我已经编写了一个以这种方式解析它的函数,并且对于您发布的示例 XML 来说,它似乎运行得相当快;)。如果您想使用它,我可以发布它。
另一个解决方案是将 XML 作为XmlDocument加载,并利用它是树状结构的事实。这样,您可以创建一个方法,在适当的情况下递归地添加适当的命名空间。不幸的是,XmlNode.Name
属性是只读的,这就是为什么您必须手动复制 xml 的整个结构才能更改某些节点的名称。我现在没时间写代码,就让你写吧。如果您遇到任何问题,请告诉我。
更新
我已经测试了您的代码和Jeff Mercado建议的代码,它们似乎都工作正常,至少在您在问题中发布的示例 XML 中是这样。确保您尝试解析的 XML 与您发布的 XML 相同。
为了使其工作并解决最初提出的添加命名空间问题,您可以使用代码,它将整个 XML 作为 a 处理String
并手动解析它:
private static String UpdateNodesWithDefaultNamespace(String xml, String defaultNamespace)
{
if (!String.IsNullOrEmpty(xml) && !String.IsNullOrEmpty(defaultNamespace))
{
int currentIndex = 0;
while (currentIndex != -1)
{
//find index of tag opening character
int tagOpenIndex = xml.IndexOf('<', currentIndex);
//no more tag openings are found
if (tagOpenIndex == -1)
{
break;
}
//if it's a closing tag
if (xml[tagOpenIndex + 1] == '/')
{
currentIndex = tagOpenIndex + 1;
}
else
{
currentIndex = tagOpenIndex;
}
//find corresponding tag closing character
int tagCloseIndex = xml.IndexOf('>', tagOpenIndex);
if (tagCloseIndex <= tagOpenIndex)
{
throw new Exception("Invalid XML file.");
}
//look for a colon within currently processed tag
String currentTagSubstring = xml.Substring(tagOpenIndex, tagCloseIndex - tagOpenIndex);
int firstSpaceIndex = currentTagSubstring.IndexOf(' ');
int nameSpaceColonIndex;
//if space was found
if (firstSpaceIndex != -1)
{
//look for namespace colon between tag open character and the first space character
nameSpaceColonIndex = currentTagSubstring.IndexOf(':', 0, firstSpaceIndex);
}
else
{
//look for namespace colon between tag open character and tag close character
nameSpaceColonIndex = currentTagSubstring.IndexOf(':');
}
//if there is no namespace
if (nameSpaceColonIndex == -1)
{
//insert namespace after tag opening characters '<' or '</'
xml = xml.Insert(currentIndex + 1, String.Format("{0}:", defaultNamespace));
}
//look for next tags after current tag closing character
currentIndex = tagCloseIndex;
}
}
return xml;
}
Run Code Online (Sandbox Code Playgroud)
您可以检查此代码以使您的应用程序正常工作,但是,我强烈建议您确定为什么建议的其他解决方案不起作用。
归档时间: |
|
查看次数: |
11787 次 |
最近记录: |