【问题标题】:parse xml without namespaces解析没有命名空间的 xml
【发布时间】:2018-12-07 19:06:06
【问题描述】:

我正在尝试从引用大量命名空间的 xml(或更准确地说:xbrl)文件中提取信息。我并不真正关心名称空间,我更希望能够搜索文件而不必指定它们。

这是一个例子:

require(magrittr)
xml <-xml2::read_xml("http://regnskaber.virk.dk/21560853/ZG9rdW1lbnRsYWdlcjovLzAzLzdlLzk4L2JiLzg4L2NiNzctNDE2ZC1hOWJmLTkxN2QxZWRkMGY0Yg.xml")

此文件包含以下节点:

<cmn:IdentificationNumberOfAuditor contextRef=\"duration_IdentificationOfAuditorDimension_cmn_auditorIdentifier_only_1\">mne18078</cmn:IdentificationNumberOfAuditor>

我知道我可以使用 xml2::xml_find_all(xml, '//cmn:IdentificationNumberOfAuditor')

但这只是在我知道命名空间前缀的情况下,而且我不确定在我需要处理的所有数千个文件中以相同的方式给出这些前缀。所以我希望这能奏效:

xml2::xml_find_all(xml2::xml_ns_strip(xml), '//IdentificationNumberOfAuditor')

因为我认为 xml_ns_strip 会剥离命名空间信息的 xml 文件。但是,xml_ns_strip 实际上似乎根本没有做任何事情,因为:

identical(xml %>% as.character(), xml_ns_strip(xml) %>% as.character())

返回真。

【问题讨论】:

  • 我不确定 xml2,但 xml_find_all 第二个参数看起来像 XPath,并且获取任何命名空间中所有元素的正确语法是 //*:IdentificationNumberOfAuditor。那么,如果你尝试xml2::xml_find_all(xml2::xml_ns_strip(xml), '//*:IdentificationNumberOfAuditor') 会返回什么?
  • 第二个参数是 XPath,但是 //*:IdentificationNumberOfAuditor 不返回节点,但是 //*[local-name() = 'IdentificationNumberOfAuditor'] 有效。但是,如果我以后需要添加更多条件等,这似乎是一种构建 XPath 的笨拙方式

标签: r xml xbrl xml2


【解决方案1】:

作为参考,我发现这个问题的最佳解决方案是使用来自 https://www.ibm.com/support/knowledgecenter/vi/SSEPGG_10.1.0/com.ibm.db2.luw.xml.doc/doc/r0054369.html 的 xslt 样式表

strip_namespaces <- function(x){
    stylesh <- '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

        <!-- keep comments -->
        <xsl:template match="comment()">
          <xsl:copy>
            <xsl:apply-templates/>
          </xsl:copy>
        </xsl:template>

      <xsl:template match="*">
        <!-- remove element prefix -->
        <xsl:element name="{local-name()}">
          <!-- process attributes -->
          <xsl:for-each select="@*">
            <!-- remove attribute prefix -->
            <xsl:attribute name="{local-name()}">
              <xsl:value-of select="."/>
            </xsl:attribute>
          </xsl:for-each>
          <xsl:apply-templates/>
        </xsl:element>
      </xsl:template>
    </xsl:stylesheet>
                      ')
  xslt::xml_xslt(x, stylesh)
}

【讨论】:

    猜你喜欢
    • 2010-11-08
    • 2023-03-12
    • 2021-10-24
    • 1970-01-01
    • 2021-05-03
    • 2014-01-10
    • 1970-01-01
    相关资源
    最近更新 更多