XmlDocument 搜索命名空间返回子级

Posted

技术标签:

【中文标题】XmlDocument 搜索命名空间返回子级【英文标题】:XmlDocument Searching for namespace returns children 【发布时间】:2020-05-28 01:06:01 【问题描述】:

我正在尝试将具有命名空间声明的节点转换为使用前缀。我的第一个尝试是只使用 xslt 来转换 xml,但我开始考虑使用 XmlDocument 类并使用 SelectNodes() 方法来实现它。我看到的问题是,当我尝试选择具有命名空间的节点时,它会选择该节点及其子节点。我认为这是因为它正在选择包含子节点的节点。

<foo xmlns="some url">
    <child>child</child>
</foo>

XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(xmlstring);
var query = xdoc.SelectNodes("//*[namespace-uri()='some url']");

查询变量将返回&lt;foo&gt;&lt;child&gt; 节点,所以当我遍历节点并将其更改为使用前缀时,我得到以下结果。

<prefix:foo>
   <prefix:child></prefix:child>
</prefix:foo>

在这种情况下,有没有办法只返回 &lt;foo&gt; 节点?是否也使用 xslt 对其进行转换更好?

我不认为在使用 XDocument 和 XElement 时可以更改名称空间或前缀,所以这就是我使用 XmlDocument 的原因。

更新

想要的结果 id 将是仅在声明所在节点上的前缀。这是有效的 xml 正确还是前缀需要在子节点上才有效?

<prefix:foo>
    <child>child</child>
</prefix:foo>

【问题讨论】:

这似乎是 XSLT 的一项任务,因为使用 DOM 或 LINQ to XML 您必须将任何元素更改为新前缀,这与使用 XSLT 所做的几乎相同,但使用XSLT 你可以写一个通用模板match="*" 然后使用&lt;xsl:element name="prefix:local-name()" namespace="namespace-uri()"&gt; 来构造需要的结果。 是的,xslt 的问题是我有同样的问题。我不想更改所有节点以添加前缀,只是那些具有命名空间声明的节点。 &lt;xsl:template match="//*[namespace-uri()='url'"&gt; 你能告诉我们你想要的结果吗? 没有任何命名空间声明不清楚你想要实现什么?您是否希望结果中的 child 元素不在命名空间中?还是保留他们在输入文档中的命名空间? 我在 xml 的根节点中添加了一个命名空间 ..xmlns:prefix="some url" 然后我想通过并重命名在节点 &lt;foo xmlns="some url"&gt;...&lt;/foo&gt; 上声明了命名空间的所有节点并将其更改为&lt;prefix:foo&gt;...&lt;/prefix:foo&gt; 但在这种情况下只有 foo 元素,而不是子元素。更有意义? 【参考方案1】:

在XPath和XSLT使用的XDM数据模型中,没有区别

<foo xmlns="some url">
    <child>child</child>
</foo>

<foo xmlns="some url">
    <child xmlns="some url">child</child>
</foo>

从逻辑上讲,命名空间在两个元素节点上都存在,并且在词法序列化中从子节点中省略它被视为方便的缩写。

所以是的,如果你搜索具有这个命名空间的东西,你会得到这两个元素。

现在,您有什么要求?我不相信您自己完全理解它们,因为您显示的所需输出实际上不是格式正确的(未声明命名空间前缀)。在您的输入中,这两个元素位于同一个命名空间中;在输出中,您似乎希望它们位于不同的命名空间中。如果你想以不同的方式处理它们,那么你将不得不使用命名空间以外的东西来区分它们。

请记住,在 XDM 中,重要的是节点的名称,而不是名称空间声明或前缀;那些只是装饰性的。节点的名称是其本地名称和名称空间 URI 的组合。您已经根据前缀描述了您的要求,但实际上重要的是命名空间。

【讨论】:

我只是展示了一个小的 xml 片段而不是一个完整的 xml 文档作为示例。xmlns 被移动到根节点并在 xml 中带有前缀,我用 xmlns 声明替换了节点在与 Martin 讨论后加上前缀。

以上是关于XmlDocument 搜索命名空间返回子级的主要内容,如果未能解决你的问题,请参考以下文章

XML命名空间问题C#

xquery 转换在元素中创建空命名空间

基于多部分 xml 根声明创建具有命名空间前缀的元素

Java SoapMessage 添加空命名空间

Django(命名空间)

空操作命名空间