gpt4 book ai didi

java - 从 XML 节点 java 生成/获取 xpath

转载 作者:IT老高 更新时间:2023-10-28 20:51:13 26 4
gpt4 key购买 nike

我对建议/ 伪代码 代码/解释 而不是实际实现 感兴趣。

  • 我想通过 xml 文档,它的所有节点
  • 检查节点是否存在属性

如果节点没有属性,get/generate String with value of its xpath
如果节点确实具有属性,则迭代槽属性列表并为包括节点在内的每个属性创建 xpath。

忠告?希望你能提供一些有用的信息

编辑:

这样做的原因是 .. 我正在 jmeter 中编写自动化测试,因此对于每个请求,我都需要验证该请求确实完成了它的工作,因此我通过使用 xpath 获取节点值来断言结果。(额外信息 -无关)

当请求很小时,手动创建断言不是问题,但对于较大的请求,它真的很痛苦..(额外信息 - 不相关)

赏金:

我正在寻找java方法

目标

我的目标是从这个 ex xml 文件中实现以下目标:

<root>
<elemA>one</elemA>
<elemA attribute1='first' attribute2='second'>two</elemA>
<elemB>three</elemB>
<elemA>four</elemA>
<elemC>
<elemB>five</elemB>
</elemC>
</root>

生成以下内容:

//root[1]/elemA[1]='one'
//root[1]/elemA[2]='two'
//root[1]/elemA[2][@attribute1='first']
//root[1]/elemA[2][@attribute2='second']
//root[1]/elemB[1]='three'
//root[1]/elemA[3]='four'
//root[1]/elemC[1]/elemB[1]='five'

解释:

  • 如果节点值/文本不为空/零,则获取 xpath ,添加 = 'nodevalue' 用于断言目的
  • 如果节点有属性,也为它们创建断言

赏金更新:

我找到了这个例子,它没有产生正确的结果,但我看起来像这样:

http://www.coderanch.com/how-to/java/SAXCreateXPath

最佳答案

更新:

@c0mrade 更新了他的问题。这是一个解决方案:

此 XSLT 转换:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

<xsl:variable name="vApos">'</xsl:variable>

<xsl:template match="*[@* or not(*)] ">
<xsl:if test="not(*)">
<xsl:apply-templates select="ancestor-or-self::*" mode="path"/>
<xsl:value-of select="concat('=',$vApos,.,$vApos)"/>
<xsl:text>&#xA;</xsl:text>
</xsl:if>
<xsl:apply-templates select="@*|*"/>
</xsl:template>

<xsl:template match="*" mode="path">
<xsl:value-of select="concat('/',name())"/>
<xsl:variable name="vnumPrecSiblings" select=
"count(preceding-sibling::*[name()=name(current())])"/>
<xsl:if test="$vnumPrecSiblings">
<xsl:value-of select="concat('[', $vnumPrecSiblings +1, ']')"/>
</xsl:if>
</xsl:template>

<xsl:template match="@*">
<xsl:apply-templates select="../ancestor-or-self::*" mode="path"/>
<xsl:value-of select="concat('[@',name(), '=',$vApos,.,$vApos,']')"/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<root>
<elemA>one</elemA>
<elemA attribute1='first' attribute2='second'>two</elemA>
<elemB>three</elemB>
<elemA>four</elemA>
<elemC>
<elemB>five</elemB>
</elemC>
</root>

准确生成所需的正确结果:

/root/elemA='one'
/root/elemA[2]='two'
/root/elemA[2][@attribute1='first']
/root/elemA[2][@attribute2='second']
/root/elemB='three'
/root/elemA[3]='four'
/root/elemC/elemB='five'

当应用于@c0mrade 新提供的文档时:

<root>
<elemX serial="kefw90234kf2esda9231">
<id>89734</id>
</elemX>
</root>

再次产生正确的结果:

/root/elemX[@serial='kefw90234kf2esda9231']
/root/elemX/id='89734'

解释:

  • 只有没有子元素或有属性的元素才会被匹配和处理。

  • 对于任何这样的元素,如果它没有子元素,则它的所有祖先或自身元素都会以特定模式处理,命名为 'path'。然后输出 "='theValue'" 部分,然后输出一个 NL 字符。

  • 然后处理匹配元素的所有属性

  • 最后,模板应用于所有子元素

  • 'path'模式下处理元素很简单:输出一个/字符和元素名称.然后,如果前面有同名的 sibling ,则输出“[numPrecSiblings+1]”部分。

  • 属性的处理很简单:首先在'path'中处理其父级的所有ancestor-or-self::元素 code>模式,则输出[attrName=attrValue]部分,后跟NL字符。

请注意:

  • namespace 中的名称以初始可读形式显示,没有任何问题。

  • 为了便于阅读,从不显示 [1] 的索引。


以下是我的初步回答(可以忽略)

这是一个纯 XSLT 1.0 解决方案:

下面是一个示例 xml 文档和一个样式表,它采用节点集参数并为每个成员节点生成一个有效的 XPath 表达式。

样式表 (buildPath.xsl):


<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
>

<xsl:output method="text"/>
<xsl:variable name="theParmNodes" select="//namespace::*[local-name() =
'myNamespace']"/>
<xsl:template match="/">
<xsl:variable name="theResult">
<xsl:for-each select="$theParmNodes">
<xsl:variable name="theNode" select="."/>
<xsl:for-each select="$theNode |
$theNode/ancestor-or-self::node()[..]">
<xsl:element name="slash">/</xsl:element>
<xsl:choose>
<xsl:when test="self::*">
<xsl:element name="nodeName">
<xsl:value-of select="name()"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::*[name(current()) =
name()])"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::*[name(current()) =
name()])"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition +
1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:otherwise> <!-- This node is not an element -->
<xsl:choose>
<xsl:when test="count(. | ../@*) = count(../@*)">
<!-- Attribute -->
<xsl:element name="nodeName">
<xsl:value-of select="concat('@',name())"/>
</xsl:element>
</xsl:when>
<xsl:when test="self::text()"> <!-- Text -->
<xsl:element name="nodeName">
<xsl:value-of select="'text()'"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::text())"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::text())"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition +
1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:when test="self::processing-instruction()">
<!-- Processing Instruction -->
<xsl:element name="nodeName">
<xsl:value-of select="'processing-instruction()'"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::processing-instruction())"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::processing-instruction())"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition +
1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<xsl:when test="self::comment()"> <!-- Comment -->
<xsl:element name="nodeName">
<xsl:value-of select="'comment()'"/>
<xsl:variable name="thisPosition"
select="count(preceding-sibling::comment())"/>
<xsl:variable name="numFollowing"
select="count(following-sibling::comment())"/>
<xsl:if test="$thisPosition + $numFollowing > 0">
<xsl:value-of select="concat('[', $thisPosition +
1, ']')"/>
</xsl:if>
</xsl:element>
</xsl:when>
<!-- Namespace: -->
<xsl:when test="count(. | ../namespace::*) =
count(../namespace::*)">

<xsl:variable name="apos">'</xsl:variable>
<xsl:element name="nodeName">
<xsl:value-of select="concat('namespace::*',
'[local-name() = ', $apos, local-name(), $apos, ']')"/>

</xsl:element>
</xsl:when>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:text>&#xA;</xsl:text>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="msxsl:node-set($theResult)"/>
</xsl:template>
</xsl:stylesheet>

xml 源代码(buildPath.xml):


<!-- top level Comment -->
<root>
<nodeA>textA</nodeA>
<nodeA id="nodeA-2">
<?myProc ?>
xxxxxxxx
<nodeB/>
<nodeB xmlns:myNamespace="myTestNamespace">
<!-- Comment within /root/nodeA[2]/nodeB[2] -->
<nodeC/>
<!-- 2nd Comment within /root/nodeA[2]/nodeB[2] -->
</nodeB>
yyyyyyy
<nodeB/>
<?myProc2 ?>
</nodeA>
</root>
<!-- top level Comment -->

结果:

/root/nodeA[2]/nodeB[2]/namespace::*[local-name() = 'myNamespace']
/root/nodeA[2]/nodeB[2]/nodeC/namespace::*[local-name() =
'myNamespace']

关于java - 从 XML 节点 java 生成/获取 xpath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4746299/

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