提问人:Raviraj Bhalerao 提问时间:9/16/2023 更新时间:9/16/2023 访问量:43
XPath 表达式,用于在 xpath 中选择父级的子级(适用于 javascript 和 c#)
XPath expression to select children of parent in xpath (that works in javascript and in c#)
问:
TLDR:我想编写一个 xpath 表达式,以使用 '..' 和 'parent::' 选择父节点的所有(在任何级别)子节点,这将在 c# 和 javascript/typescript 中工作。
我仅限于 xsd 1.0。我不想使用前面的同级轴。
我的xml看起来像
<tns:s03.q01 id="s03.q01" text="Select the specific issues encountered (please select all that apply) and indicate the corresponding MBAs" description="" isAnsewerRequired="true" type="Question">
<tns:choices>
<tns:multiChoiceAssert condition="count(parent::tns:choices/*[@value='true']) = 0" message="'{$locator}\Choices' must have atleast one choice selected." relevantNodeLocator="string(../../@id)" />
<tns:s03.q01.c01 value="true" id="s03.q01.c01" text="Bias" description="" type="Choice">
<tns:selectMBAAssert condition="parent::*[@value='true'] and count(parent::*/tns:mba) = 0" message="'Select MBAs for {$locator}'." relevantNodeLocator="string(../@id)" />
<tns:selectValueAssert condition="parent::*[@value='false'] and count(parent::*/tns:mba) > 0" message="Select '{$locator}'." relevantNodeLocator="string(../@id)" />
<tns:mba>m1</tns:mba>
<tns:mba>m2</tns:mba>
</tns:s03.q01.c01>
<tns:s03.q01.c02 id="s03.q01.c02" text="Poor measurement quality" description="" type="Choice" value="false">
<tns:selectMBAAssert condition="parent::*[@value='true'] and count(parent::*/tns:mba) = 0" message="'Select MBAs for {$locator}'." relevantNodeLocator="string(../@id)" />
<tns:selectValueAssert condition="parent::*[@value='false'] and count(parent::*/tns:mba) > 0" message="Select '{$locator}'." relevantNodeLocator="string(../@id)" />
</tns:s03.q01.c02>
<tns:s03.q01.c03 id="s03.q01.c03" text="Statistically significant MUF" description="" type="Choice" value="false">
<tns:selectMBAAssert condition="parent::*[@value='true'] and count(parent::*/tns:mba) = 0" message="'Select MBAs for {$locator}'." relevantNodeLocator="string(../@id)" />
<tns:selectValueAssert condition="parent::*[@value='false'] and count(parent::*/tns:mba) > 0" message="Select '{$locator}'." relevantNodeLocator="string(../@id)" />
</tns:s03.q01.c03>
</tns:choices>
<tns:comment id="s03.q01.comment" title="Comments" description="If the answer to the previous questions is “Yes,” please provide the details, including the document type (initial DIQ, DIQ update, initial LOF information, LOF information update), facility/MBA code, the date due and the date received.">
<tns:s03.q01.comment dateRequested="2023-03-23" documentType="2" facility-mbaCode="m1" />
<tns:s03.q01.comment dateRequested="2023-04-24" documentType="4" facility-mbaCode="f2" />
</tns:comment>
</tns:s03.q01>
我正在使用 c# 和 javascript,因此我仅限于 xsd 1.0 我使用 selectMBAAssert 和 selectValueAssert 等节点定义验证,并在“condition”属性中使用规则。因此,在解析 xml 时,我选择所有具有 @condition 属性的节点,并在同一节点的上下文中评估条件。
这样做的代码在 c# 中工作正常,如下所示
XmlDocument document = getDocumentWithSchema(xmlTextReader, schemaPath);//this is a method to load document with schema and xml.
ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
var nsmgr = new XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace("tns", "http://tempuri.org/XMLSchema2.xsd");
document.Validate(eventHandler);
//var nav = document.CreateNavigator();
var list = document.SelectNodes("//*[@condition]", nsmgr);
foreach (XmlNode node in list)
{
var condition = node.Attributes["condition"].Value;
var nodeNav = node.CreateNavigator();
var result = nodeNav.evaluateXPath(condition, nsmgr);
//If the condition is "//tns:choices" results contains 1 element.
if ((bool)result)
{
var errorMsg = node.Attributes["message"].Value;
var locator = node.Attributes["relevantNodeLocator"].Value;
var nodeLocator = nodeNav.evaluateXPath(locator, nsmgr);
errorMsg = errorMsg.Replace("{$locator}", nodeLocator.ToString());
Console.WriteLine($"Validation error:{errorMsg}");
}
}
但是,打字稿中的代码确实以相同的方式工作。
validateXML(questionId: any, xmlData: Document) {
var conditionNodes = xmlData.evaluate("//*[@id='" + questionId + "']/*[@condition]", xmlData.documentElement, null, XPathResult.ANY_TYPE, null);
var toretErrors: string = "";
try {
var currnetConditionNode: any = conditionNodes.iterateNext();
while (currnetConditionNode) {
//console.log(thisNode.textContent);
var atributeValue = currnetConditionNode.attributes["condition"].nodeValue;
var validationResult = xmlData.evaluate(atributeValue, currnetConditionNode, this.NSResolver, XPathResult.ANY_TYPE, null)
console.log(validationResult);
if (validationResult.booleanValue) {
toretErrors += currnetConditionNode.attributes["message"].nodeValue;
}
currnetConditionNode = conditionNodes.iterateNext();
}
}
catch (e) {
console.error('Error: Document parsing error ' + e);
}
return toretErrors;
}
NSResolver(nsPrefix) {
if (nsPrefix == "tns") {
return "http://tempuri.org/XMLSchema2.xsd";
}
return null;
}
如何在 selectMBAAssert 节点中编写条件以选择所有(在任何级别)父级的 tns:mba 类型的子项?
我认为与这个问题相关的另一个问题是,“..”和“parent::”可以互换吗?如何使用它们来编写条件属性的脚本?
很抱歉让它变得冗长。如果您需要更多详细信息,请告诉我。
答: 暂无答案
评论
..
只是 的简写,所以它们应该是可以互换的parent::
..
parent::