C# c语言中不区分大小写的XML解析器#
我知道,使用XML所做的一切都是区分大小写的 然而,现在我发现自己处于这样一种情况:如果我以某种方式使xml名称/属性识别不区分大小写,那么我正在编写的软件将产生更少的错误。不区分大小写的XPath将是上帝派来的C# c语言中不区分大小写的XML解析器#,c#,xml,linq,xslt,xpath,C#,Xml,Linq,Xslt,Xpath,我知道,使用XML所做的一切都是区分大小写的 然而,现在我发现自己处于这样一种情况:如果我以某种方式使xml名称/属性识别不区分大小写,那么我正在编写的软件将产生更少的错误。不区分大小写的XPath将是上帝派来的 在c#中是否有一种简单的方法/库可以做到这一点?XML是文本。在加载到您正在使用的任何解析器之前,只需ToLowerit 只要您不必根据模式进行验证,并且不介意所有值都是小写的,这就可以正常工作 事实上,任何XML解析器都是区分大小写的。如果不是,它就不是XML解析器。您可以创建不区
在c#中是否有一种简单的方法/库可以做到这一点?XML是文本。在加载到您正在使用的任何解析器之前,只需
ToLower
it
只要您不必根据模式进行验证,并且不介意所有值都是小写的,这就可以正常工作
事实上,任何XML解析器都是区分大小写的。如果不是,它就不是XML解析器。您可以创建不区分大小写的方法(可用性扩展),例如:
公共静态类XDocumentExtensions
{
公共静态IEnumerable ElementsCasensitive(此XContainer源,
XName(名称)
{
返回source.Elements()
.Where(e=>e.Name.Namespace==Name.Namespace
&&e.Name.LocalName.Equals(Name.LocalName,StringComparison.OrdinalIgnoreCase));
}
}
一个XMl文档可以有两个不同的元素,分别命名为:MyName
和MyName
——它们是不同的。将它们转换为相同的名称或将其视为相同的名称是一个可能产生严重后果的错误。
如果上述情况并非如此,那么这里有一个更精确的解决方案,使用XSLT将文档处理为只有小写元素名和小写属性名的文档:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vUpper" select=
"'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="vLower" select=
"'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()=local-name()]" priority="2">
<xsl:element name="{translate(name(), $vUpper, $vLower)}"
namespace="{namespace-uri()}">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="*" priority="1">
<xsl:element name=
"{substring-before(name(), ':')}:{translate(local-name(), $vUpper, $vLower)}"
namespace="{namespace-uri()}">
<xsl:apply-templates select="node()|@*"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*[name()=local-name()]" priority="2">
<xsl:attribute name="{translate(name(), $vUpper, $vLower)}"
namespace="{namespace-uri()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="@*" priority="1">
<xsl:attribute name=
"{substring-before(name(), ':')}:{translate(local-name(), $vUpper, $vLower)}"
namespace="{namespace-uri()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
当此转换应用于任何XML文档时,例如此文档:
<authors xmlns:user="myNamespace">
<?ttt This is a PI ?>
<Author xmlns:user2="myNamespace2">
<Name idd="VH">Victor Hugo</Name>
<user2:Name idd="VH">Victor Hugo</user2:Name>
<Nationality xmlns:user3="myNamespace3">French</Nationality>
</Author>
<!-- This is a very long comment the purpose is
to test the default stylesheet for long comments-->
<Author Period="classical">
<Name>Sophocles</Name>
<Nationality>Greek</Nationality>
</Author>
<author>
<Name>Leo Tolstoy</Name>
<Nationality>Russian</Nationality>
</author>
<Author>
<Name>Alexander Pushkin</Name>
<Nationality>Russian</Nationality>
</Author>
<Author Period="classical">
<Name>Plato</Name>
<Nationality>Greek</Nationality>
</Author>
</authors>
<authors><?ttt This is a PI ?>
<author>
<name idd="VH">Victor Hugo</name>
<user2:name xmlns:user2="myNamespace2" idd="VH">Victor Hugo</user2:name>
<nationality>French</nationality>
</author><!-- This is a very long comment the purpose is
to test the default stylesheet for long comments-->
<author period="classical">
<name>Sophocles</name>
<nationality>Greek</nationality>
</author>
<author>
<name>Leo Tolstoy</name>
<nationality>Russian</nationality>
</author>
<author>
<name>Alexander Pushkin</name>
<nationality>Russian</nationality>
</author>
<author period="classical">
<name>Plato</name>
<nationality>Greek</nationality>
</author>
</authors>
维克多·雨果
维克多·雨果
法语
索福克勒斯
希腊人
列夫·托尔斯泰
俄语
亚历山大·普希金
俄语
柏拉图
希腊人
生成所需的正确结果(元素和属性名称转换为小写):
<authors xmlns:user="myNamespace">
<?ttt This is a PI ?>
<Author xmlns:user2="myNamespace2">
<Name idd="VH">Victor Hugo</Name>
<user2:Name idd="VH">Victor Hugo</user2:Name>
<Nationality xmlns:user3="myNamespace3">French</Nationality>
</Author>
<!-- This is a very long comment the purpose is
to test the default stylesheet for long comments-->
<Author Period="classical">
<Name>Sophocles</Name>
<Nationality>Greek</Nationality>
</Author>
<author>
<Name>Leo Tolstoy</Name>
<Nationality>Russian</Nationality>
</author>
<Author>
<Name>Alexander Pushkin</Name>
<Nationality>Russian</Nationality>
</Author>
<Author Period="classical">
<Name>Plato</Name>
<Nationality>Greek</Nationality>
</Author>
</authors>
<authors><?ttt This is a PI ?>
<author>
<name idd="VH">Victor Hugo</name>
<user2:name xmlns:user2="myNamespace2" idd="VH">Victor Hugo</user2:name>
<nationality>French</nationality>
</author><!-- This is a very long comment the purpose is
to test the default stylesheet for long comments-->
<author period="classical">
<name>Sophocles</name>
<nationality>Greek</nationality>
</author>
<author>
<name>Leo Tolstoy</name>
<nationality>Russian</nationality>
</author>
<author>
<name>Alexander Pushkin</name>
<nationality>Russian</nationality>
</author>
<author period="classical">
<name>Plato</name>
<nationality>Greek</nationality>
</author>
</authors>
维克多·雨果
维克多·雨果
法语
索福克勒斯
希腊人
列夫·托尔斯泰
俄语
亚历山大·普希金
俄语
柏拉图
希腊人
一旦文档转换为所需的格式,您就可以对转换后的文档执行任何所需的处理。首先,我将使用
SAX
解析将所有标记和属性名称转换为小写,保持值不变,即使用XmlTextReader
我使用另一种解决方案。人们之所以希望这样做,是因为您不想在属性中复制类文件中属性的名称。因此,我要做的是向所有属性添加自定义属性:
[AttributeUsage(AttributeTargets.Property)]
public class UsePropertyNameToLowerAsXmlElementAttribute: XmlElementAttribute
{
public UsePropertyNameToLowerAsXmlElementAttribute([CallerMemberName] string propertyName = null)
: base(propertyName?.ToLower())
{
}
}
通过这种方式,XML序列化程序可以将小写属性映射到CamelCased类
类上的属性仍然有一个装饰器,表示有些不同,但您不需要为每个属性标记一个名称:
public class Settings
{
[UsePropertyNameToLowerAsXmlElement]
public string VersionId { get; set; }
[UsePropertyNameToLowerAsXmlElement]
public int? ApplicationId { get; set; }
}
不太可能。但是您可以执行
XElement.Parse(xmlText.Tolower())
一个XMl文档可以有两个不同的元素分别命名:MyName
和MyName
——这两个元素应该是不同的。将它们转换为相同的名称/将其视为相同的名称是一个可能会产生严重后果的错误。但您可能不想降低您的values@Chad-可能。我确实在回答中提出了这个警告,我已经想到了。在大多数情况下,这是可行的,但有时字段可能包含信息,我希望在其中保留案例。比如,密码、散列和其他外部世界的东西。另一方面,我真的不需要区分XHTML中的Name和Name属性。XHTML中有一个Name
属性,或者它是Name
?有时是一个,有时是另一个。这就是我所面临的问题。有没有任何C++代码将XML属性和节点转换成大写字母或低字母?@ DavidAlex:你需要调用一个可以在C++中调用的XSLT处理器的函数。您需要确定哪一个最适合您——MSXML/MSXSL、Saxon/C或其他产品。然后阅读所选产品的文档并理解代码示例。@DimitreNovatchev,我想使用MSXML/MSXSL。您是否有读取xml和运行xsl转换以将属性和节点转换为大写字母或小写字母的示例代码?我是XSL转换新手,需要帮助!。Thanks@DavidAlex--您可以使用Microsoft的MSXML6 SDK--可以从以下位置下载:。这应该包含主要类型/类的大量文档,以及如何从不同编程语言调用其方法的示例。有一个更老的版本——用于MSXML4,可以在这里下载:这两个版本中的任何一个都应该适合您的需要和需要requirements@DimitreNovatchev,您提供的xslt会导致根元素上的所有属性丢失。甚至在上面的示例中也显示了这一点。为了不丢失它们,我会在xlst中更改什么?