你做的每一件事情都是区分大小写的,我知道。
但是,现在我发现自己处于这样一种情况中,如果某种方式使xml名称/属性识别不区分大小写,我编写的软件将产生更少的错误。不区分大小写的XPath会拯救我。
在C#中有没有简单的方法/库可以实现这一点?
一个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>
一旦文档转换成您想要的形式,您就可以对转换后的文档进行任何所需的处理。
<xsl:apply-templates select="node()|@*"/>
之前添加此内容:<xsl:copy-of select="namespace::*"/>
- Dimitre Novatchev您可以创建不区分大小写的方法(通过扩展以提高可用性),例如:
public static class XDocumentExtensions
{
public static IEnumerable<XElement> ElementsCaseInsensitive(this XContainer source,
XName name)
{
return source.Elements()
.Where(e => e.Name.Namespace == name.Namespace
&& e.Name.LocalName.Equals(name.LocalName, StringComparison.OrdinalIgnoreCase));
}
}
XML是文本。在加载到您正在使用的任何解析器之前,只需将其 ToLower
。
只要您不必针对模式进行验证并且不介意值全部为小写,这应该可以正常工作。
事实上,任何XML解析器都会区分大小写。如果不是这样,它就不会成为XML解析器。
Name
属性还是name
属性? - John Saunders"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
转换为"xmlns:xsl="http://www.w3.org/1999/xsl/transform"
,那么这个XML文档(一个语法上有效的XSLT样式表)现在被XSLT处理器拒绝了。 - Dimitre Novatchev我使用另一种解决方案。人们想要这样做的原因是因为你不想在类文件中的属性和属性中重复使用名称。所以我的做法是为所有属性添加一个自定义属性:
OriginalAnswerAttribute
[AttributeUsage(AttributeTargets.Property)]
public class UsePropertyNameToLowerAsXmlElementAttribute: XmlElementAttribute
{
public UsePropertyNameToLowerAsXmlElementAttribute([CallerMemberName] string propertyName = null)
: base(propertyName?.ToLower())
{
}
}
这样XML序列化程序就可以将小写属性映射到驼峰命名的类。
类上的属性仍然有一个装饰器,说明某些东西不同,但您没有标记每个属性名称的开销:
最初的回答:
public class Settings
{
[UsePropertyNameToLowerAsXmlElement]
public string VersionId { get; set; }
[UsePropertyNameToLowerAsXmlElement]
public int? ApplicationId { get; set; }
}
我会从转换所有标签和属性名称为小写开始,保留值不变,使用 SAX
解析,即使用 XmlTextReader
。
XElement.Parse(xmlText.Tolower())
。 - H HMyName
和myName
--它们被设计成不同的。将它们转换/处理为相同的名称是一个错误,可能会产生严重的后果。 - Dimitre Novatchev