gpt4 book ai didi

xml - 从 XML 中提取信息的 XPath 查询

转载 作者:行者123 更新时间:2023-12-03 16:27:40 26 4
gpt4 key购买 nike

这可能是一个棘手的问题,尽管我不是 XPath 方面的专家。这几天绞尽脑汁。
我正在尝试从 XML 文件中提取某些元素以创建一个表,然后我需要通过 extractValue 从中提取单个值:

SELECT [extractValue statements] FROM TABLE( XMLSequence( extract( lv_xml, lv_xpath) ) ) t;

表中的每一行(一列)都应包含一个 XML 片段,其中所需元素出现的次数不超过一次。它的父节点也应该被提取到表中。问题是在 XML 源中,所需元素可能也有符合我要求的兄弟元素。我需要 sibling 在我的结果表中单独一行。

XML 看起来与此类似(只是内容更多,并且 ID 不同):
<element id="Address">
<assignment name="name1" category="cat1" />
<field id="field1">
</field>
<field id="field2">
</field>
<field id="field3">
<assignment name="name5" category="cat2" />
<assignment name="name12" category="cat2" />
</field>
</element>
<element id="PersonInfo">
<field id="field1">
</field>
<field id="field2">
<assignment name="name17" category="cat1" />
</field>
<field id="field3">
</field>
<field id="field4">
</field>
</element>
etc etc

我想要“分配”元素,以及它们的祖先。但就像我上面所说的,我的结果表每行不能包含一个以上的“赋值”元素。如果他们中的两个是 sibling ,我到目前为止所尝试的似乎可以提取很多。
除此之外,“赋值”可以是“元素”的子元素或“字段”的子元素,这可能会增加复杂性。

为了使其 100% 清楚,我的结果需要如下所示(以便后续的 extractValue 工作):
<element id="Address">
<assignment name="name1" category="cat1" />
</element>

<element id="Address">
<field id="field3">
<assignment name="name5" category="cat2" />
</field>
</element>

<element id="Address">
<field id="field3">
<assignment name="name12" category="cat2" />
</field>
</element>

<element id="PersonInfo">
<field id="field2">
<assignment name="name17" category="cat1" />
</field>
</element>

我一直在玩 XPath 查询,但到目前为止还没有运气。我期待
//assignment/ancestor-or-self::*

可能会成功,但我显然错了。有没有办法实现我想要的?

最佳答案

给定输入:

<?xml version="1.0" encoding="UTF-8"?>

<root>
<element id="Address">
<assignment name="name1" category="cat1"/>
<field id="field1"></field>
<field id="field2"></field>
<field id="field3">
<assignment name="name5" category="cat2"/>
<assignment name="name12" category="cat2"/>
</field>
</element>
<element id="PersonInfo">
<field id="field1"></field>
<field id="field2">
<assignment name="name17" category="cat1"/>
</field>
<field id="field3"></field>
<field id="field4"></field>
</element>
</root>
使用给定的 XSL 样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">
<xsl:apply-templates select="//assignment"/>
</xsl:template>

<xsl:template match="assignment">
<xsl:apply-templates select="ancestor::element">
<xsl:with-param name="assignment-name" select="@name"/>
<xsl:with-param name="field-id" select="ancestor::field/@id"/>
</xsl:apply-templates>
</xsl:template>

<xsl:template match="element">
<xsl:param name="assignment-name"/>
<xsl:param name="field-id"/>

<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy">
<xsl:with-param name="assignment-name" select="$assignment-name"/>
<xsl:with-param name="field-id" select="$field-id"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="@*|node()" mode="copy">
<xsl:param name="assignment-name"/>
<xsl:param name="field-id"/>

<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy">
<xsl:with-param name="assignment-name" select="$assignment-name"/>
<xsl:with-param name="field-id" select="$field-id"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="field" mode="copy">
<xsl:param name="assignment-name"/>
<xsl:param name="field-id"/>

<xsl:if test="@id=$field-id">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy">
<xsl:with-param name="assignment-name" select="$assignment-name"/>
<xsl:with-param name="field-id" select="$field-id"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:if>
</xsl:template>

<xsl:template match="assignment" mode="copy">
<xsl:param name="assignment-name"/>
<xsl:param name="field-id"/>

<xsl:if test="@name=$assignment-name">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy">
<xsl:with-param name="assignment-name" select="$assignment-name"/>
<xsl:with-param name="field-id" select="$field-id"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:if>
</xsl:template>

</xsl:stylesheet>
将产生输出:
<?xml version="1.0" encoding="UTF-8"?>

<element id="Address">
<assignment name="name1" category="cat1"/>
</element>
<element id="Address">
<field id="field3">
<assignment name="name5" category="cat2"/>
</field>
</element>
<element id="Address">
<field id="field3">
<assignment name="name12" category="cat2"/>
</field>
</element>
<element id="PersonInfo">
<field id="field2">
<assignment name="name17" category="cat1"/>
</field>
</element>
解释:
首先我们必须匹配所有的 assignment元素。这些赋值元素可以有 fieldelement作为直接 parent 。他们将 id 作为唯一标识符。和 name对于 elementfield分别。然后我们只是递归复制并额外检查 id 和/或 name 是否匹配。我正在使用 modes以确保我没有无限递归。
编辑
id检查似乎没有必要,你可以检查它是否有一个带名字的子任务。此解决方案效果更好,因为它允许嵌套 field元素。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">
<xsl:apply-templates select="//assignment"/>
</xsl:template>

<xsl:template match="assignment">
<xsl:apply-templates select="ancestor::element">
<xsl:with-param name="assignment-name" select="@name"/>
</xsl:apply-templates>
</xsl:template>

<xsl:template match="element">
<xsl:param name="assignment-name"/>

<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy">
<xsl:with-param name="assignment-name" select="$assignment-name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="@*|node()" mode="copy">
<xsl:param name="assignment-name"/>

<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy">
<xsl:with-param name="assignment-name" select="$assignment-name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>

<xsl:template match="field" mode="copy">
<xsl:param name="assignment-name"/>

<xsl:if test="child::assignment[@name=$assignment-name]">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy">
<xsl:with-param name="assignment-name" select="$assignment-name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:if>
</xsl:template>

<xsl:template match="assignment" mode="copy">
<xsl:param name="assignment-name"/>

<xsl:if test="@name=$assignment-name">
<xsl:copy>
<xsl:apply-templates select="@*|node()" mode="copy">
<xsl:with-param name="assignment-name" select="$assignment-name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

关于xml - 从 XML 中提取信息的 XPath 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35719024/

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