gpt4 book ai didi

xml - 从 xml 文档中读取命名空间

转载 作者:行者123 更新时间:2023-12-04 06:48:09 28 4
gpt4 key购买 nike

如何从 XML 文档中读取 namespace ?

<fx:FIBEX xmlns:fx="http://www.asam.net/xml/fbx" xmlns:can="http://www.asam.net/xml/fbx/can" xmlns:flexray="http://www.asam.net/xml/fbx/flexray"      
xmlns:ho="http://www.asam.net/xml" xmlns:ni="http://www.ni.com/xnet"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.asam.net/xml/fbx/all http://www.asam.net/xml/fbx/2_0_1/xsd/fibex4multiplatform.xsd"
VERSION="2.0.1">

如何从此根元素读取命名空间?

事实上,最终的问题是“如何使用 xPath 检索节点,例如
//fx:ELEMENTS/fx:CLUSTERS/fx:CLUSTER 

?

我已经用该字符串尝试过 XmlDocument.SelectSingleNode() ,但这给了我一些关于 XmlNamespaces 的错误,我在谷歌上发现你需要有一个 XmlNamespaceManager 。

最佳答案

您的问题实际上似乎包括两个不同的问题:

  • 如何选择在某个命名空间中声明的元素?
  • 如何选择元素的命名空间节点?

  • 问题 1

    为了选择某些命名空间中的节点,您需要指定前缀命名空间映射。所有 XPath 处理器都允许这样做,但如何完成取决于实现。通常,这意味着创建一对 - 前缀和 URI - 然后将这对添加为命名空间上下文。 URI 很重要。它需要与元素的命名空间 URI 完全相同。前缀不需要与文档中使用的相同,它可以是任何东西,但您需要一个前缀,即使元素在默认命名空间中,因此没有前缀。

    在您的 XPath 解析器知道所需的 namespace 后,您可以像在问题中所做的那样选择元素: //fx:ELEMENTS/fx:CLUSTERS/fx:CLUSTER .确保您使用的前缀与映射中使用的前缀相同(如果前缀与文档中的前缀不同)。请注意,在 XPath 表达式中,始终假定没有前缀的元素没有命名空间,因此即使从默认命名空间中选择元素,也需要在 XPath 表达式中使用命名空间前缀。

    对于脏黑客,您还可以尝试完全避免使用元素名称。在 Xpath *匹配所有元素节点和 node()所有节点。您可以创造性地使用使用函数的谓词来缩小选择范围,例如 name() , local-name() , position()last() .例如 XPath 表达式 //*[name()='fx:CLUSTER']选择所有具有前缀“fx”和本地名称“CLUSTER”的元素,即使没有前缀命名空间映射也能工作。请注意,在 XML 中,前缀不能保证保持不变,它们也可以在文档中重用/覆盖,以便相同的前缀指代文档不同部分中的不同 URI。

    问题2

    使用 namespace:: 选择命名空间节点轴。命名空间节点名称的本地部分是命名空间前缀,字符串值是命名空间 URI。默认命名空间的节点名称为空。您可以选择所有具有 URI http://example.com/ns 的命名空间节点使用 XPath 表达式 //namespace::*[.=http://example.com/ns]并选择所有前缀为“px:”的命名空间节点,使用 //namespace::*[name()='px'] .就像属性节点一样,命名空间节点不是它所属元素的子元素,但该元素是该命名空间节点的父元素。使用 parent:: axis 获取命名空间节点的所有者。

    命名空间不需要在根元素中声明(尽管这很常见且非常合理)但它们可以在任何元素中声明。搜索根元素的命名空间节点并不能保证您知道本文档中使用的所有命名空间 URI 和前缀。

    问题在于所有元素都具有一个或多个命名空间节点,而不管该元素是否具有显式命名空间声明。元素具有一组命名空间节点,一个用于默认命名空间(如果它在此元素的范围内),一个用于此元素范围内的每个前缀,包括 xml 前缀。下面是不同情况下命名空间节点的代码示例。

    此示例有 3 个文件:一个具有不同 namespace 的 XML 文档、一个为每个元素打印 namespace 节点值的 XSLT 文档以及 XSLT 文档的输出。

    已处理的 XML 文档
    <root xmlns:ns1="http://example.com/namespace-1">
    <nothing/>
    <default xmlns="http://example.com/default">
    <override xmlns=""/>
    </default>
    <ns1:namespace-1 ns1:attribute-1="x" attribute-2="y"/>
    <ns2:namespace-2 xmlns:ns2="http://example.com/namespace-2"/>
    </root>

    XSLT 文档
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output encoding="utf-8" method="text"/>

    <xsl:template match="/">
    <xsl:text>Find and print all element names and namespace nodes&#10;&#10;</xsl:text>
    <xsl:apply-templates select="//*|//@*"/>
    <xsl:text>End of tests&#10;</xsl:text>
    </xsl:template>

    <xsl:template match="*|@*">
    <xsl:text>name = "</xsl:text>
    <xsl:value-of select="name(.)"/>
    <xsl:text>"&#10;</xsl:text>
    <xsl:text>namespace URI = "</xsl:text>
    <xsl:value-of select="namespace-uri(.)"/>
    <xsl:text>"&#10;</xsl:text>
    <xsl:text>This node has </xsl:text>
    <xsl:value-of select="count(./namespace::*)"/>
    <xsl:text> namespace nodes:&#10;</xsl:text>
    <xsl:for-each select="./namespace::*">
    <xsl:value-of select="position()"/>
    <xsl:text>. namespace prefix = "</xsl:text>
    <xsl:value-of select="name(.)"/>
    <xsl:text>"&#10; namespace URI = "</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>"&#10;</xsl:text>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>
    </xsl:template>
    </xsl:stylesheet>

    XSLT 文档的输出
    Find and print all element names and namespace nodes

    name = "root"
    namespace URI = ""
    This node has 2 namespace nodes:
    1. namespace prefix = "xml"
    namespace URI = "http://www.w3.org/XML/1998/namespace"
    2. namespace prefix = "ns1"
    namespace URI = "http://example.com/namespace-1"

    name = "nothing"
    namespace URI = ""
    This node has 2 namespace nodes:
    1. namespace prefix = "xml"
    namespace URI = "http://www.w3.org/XML/1998/namespace"
    2. namespace prefix = "ns1"
    namespace URI = "http://example.com/namespace-1"

    name = "default"
    namespace URI = "http://example.com/default"
    This node has 3 namespace nodes:
    1. namespace prefix = "xml"
    namespace URI = "http://www.w3.org/XML/1998/namespace"
    2. namespace prefix = "ns1"
    namespace URI = "http://example.com/namespace-1"
    3. namespace prefix = ""
    namespace URI = "http://example.com/default"

    name = "override"
    namespace URI = ""
    This node has 3 namespace nodes:
    1. namespace prefix = "xml"
    namespace URI = "http://www.w3.org/XML/1998/namespace"
    2. namespace prefix = "ns1"
    namespace URI = "http://example.com/namespace-1"
    3. namespace prefix = ""
    namespace URI = ""

    name = "ns1:namespace-1"
    namespace URI = "http://example.com/namespace-1"
    This node has 2 namespace nodes:
    1. namespace prefix = "xml"
    namespace URI = "http://www.w3.org/XML/1998/namespace"
    2. namespace prefix = "ns1"
    namespace URI = "http://example.com/namespace-1"

    name = "ns1:attribute-1"
    namespace URI = "http://example.com/namespace-1"
    This node has 0 namespace nodes:

    name = "attribute-2"
    namespace URI = ""
    This node has 0 namespace nodes:

    name = "ns2:namespace-2"
    namespace URI = "http://example.com/namespace-2"
    This node has 3 namespace nodes:
    1. namespace prefix = "xml"
    namespace URI = "http://www.w3.org/XML/1998/namespace"
    2. namespace prefix = "ns1"
    namespace URI = "http://example.com/namespace-1"
    3. namespace prefix = "ns2"
    namespace URI = "http://example.com/namespace-2"

    End of tests

    该示例显示的一些内容:
  • 所有元素都有一个用于 xml 命名空间的节点
  • 元素 rootnothing即使元素不使用它,也有一个带有前缀命名空间“namespace-1”的节点
  • 默认命名空间的名称为空,如 default 所示
  • 元素 root没有默认命名空间的节点,但 override有,即使它们都不属于命名空间。这是因为 override有一个默认的命名空间声明,只有在这种情况下它才会被重置为空。
  • namespace-1具有与元素 nothing 相似的命名空间节点尽管另一个带有前缀并使用命名空间而另一个没有
  • namespace-2是唯一具有 ns2 节点的元素前缀,因为同级元素不在命名空间声明的范围内
  • 有趣的是,属性可以属于一个命名空间,但它们似乎仍然没有任何命名空间节点。根据规范,命名空间节点也具有扩展名称,但 URI 始终为空。

  • 比较命名空间时,请记住元素不共享命名空间节点。即使父子节点具有所有相似的命名空间节点,它们实际上也不是相同的节点。就像两个不同对象的变量不一样,即使它们具有相同的名称和相同的值。

    关于xml - 从 xml 文档中读取命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3494093/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com