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']");
查询变量将返回<foo>
和<child>
节点,所以当我遍历节点并将其更改为使用前缀时,我得到以下结果。
<prefix:foo>
<prefix:child></prefix:child>
</prefix:foo>
在这种情况下,有没有办法只返回 <foo>
节点?是否也使用 xslt 对其进行转换更好?
我不认为在使用 XDocument 和 XElement 时可以更改名称空间或前缀,所以这就是我使用 XmlDocument 的原因。
更新
想要的结果 id 将是仅在声明所在节点上的前缀。这是有效的 xml 正确还是前缀需要在子节点上才有效?
<prefix:foo>
<child>child</child>
</prefix:foo>
【问题讨论】:
这似乎是 XSLT 的一项任务,因为使用 DOM 或 LINQ to XML 您必须将任何元素更改为新前缀,这与使用 XSLT 所做的几乎相同,但使用XSLT 你可以写一个通用模板match="*"
然后使用<xsl:element name="prefix:local-name()" namespace="namespace-uri()">
来构造需要的结果。
是的,xslt 的问题是我有同样的问题。我不想更改所有节点以添加前缀,只是那些具有命名空间声明的节点。 <xsl:template match="//*[namespace-uri()='url'">
你能告诉我们你想要的结果吗?
没有任何命名空间声明不清楚你想要实现什么?您是否希望结果中的 child
元素不在命名空间中?还是保留他们在输入文档中的命名空间?
我在 xml 的根节点中添加了一个命名空间 ..xmlns:prefix="some url"
然后我想通过并重命名在节点 <foo xmlns="some url">...</foo>
上声明了命名空间的所有节点并将其更改为<prefix:foo>...</prefix:foo>
但在这种情况下只有 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 搜索命名空间返回子级的主要内容,如果未能解决你的问题,请参考以下文章