Apache XMLSchema 核心 XSD/XML 解析器将根元素显示为所有子元素的父元素,而不是其直接父元素
Posted
技术标签:
【中文标题】Apache XMLSchema 核心 XSD/XML 解析器将根元素显示为所有子元素的父元素,而不是其直接父元素【英文标题】:Apache XMLSchema core XSD/XML parser shows the root element as parent for all children instead of its immediate parent 【发布时间】:2021-06-28 06:01:39 【问题描述】:我正在尝试使用 Apache XMLSchema Core
解析 XSD
。我能够解析文件并将Parent
及其Child Element
信息存储在HashMap
中。
每个Child
元素都存储在XmlSchemaElement
类型中,该类型还包含该子元素的Parent
信息。当我尝试查看与子元素相关的信息时,它会显示所有的 Root
元素而不是其直接父元素。
例如:在我的XSD
中,RestaurantMenu
是Root
元素,其直接子元素是Food
。此外,Food
有子元素name
、price
、calories
等。当我看到name
的父元素时,我希望它是Food
,因为那是直接父元素,但在Debug
显示期间RestaurantMenu
作为其父级,这有点令人困惑。
我想知道如何获取与每个元素的直接父级相关的信息。
以下是我的XSD
文件:
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="RestaurantMenu">
<xs:complexType>
<xs:sequence>
<xs:element name="food" maxOccurs="5" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name" />
<xs:element type="xs:string" name="price" />
<xs:element type="xs:string" name="description" />
<xs:element type="xs:short" name="calories" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
以下是我使用Apache XmlSchema Core XML Parser
编写的代码:
我正在尝试Debug
:
List<XmlSchemaElement> childElements = getElementType(new QName("food"));
System.out.println(childElements.get(0));
上面的代码将返回食物的所有Children
元素:name
、price
、calories
、description
、ingredients
。然后我试图查看其中一个元素的父级,即name
。以下是我正在采取的调试路径:
childElements -> [0] -> namedDelegate -> parentSchema -> items -> [0] -> namedDelegate -> qName.
在这个qName
中,我期待food
作为我的直系父母,但我得到了RestaurantMenu
,这是我的Root
xsd 元素。
请在下面找到完整的代码:
public class TestParser
private static XmlSchemaCollection xmlSchemaCollection;
private static Map<QName, List<XmlSchemaElement>> xsdElements = new HashMap<QName, List<XmlSchemaElement>>();
private static List<XmlSchemaElement> schemaElements = new ArrayList<XmlSchemaElement>();
public static void main(String[] args) throws URISyntaxException, FileNotFoundException, UnsupportedEncodingException
// Path for the file which is stored within the Resource folder
String xsdPath = Paths.get(TestParser.class.getClassLoader().getResource("test.xsd").toURI()).toFile().getAbsolutePath();
String filePath = Path.of(xsdPath).toString();
InputStream is = new FileInputStream(filePath);
xmlSchemaCollection = new XmlSchemaCollection();
// Schema contain the complete XSD content which needs to be parsed
XmlSchema schema = xmlSchemaCollection.read(new StreamSource(is));
// schema.write(System.out);
// Get the root element from XSD
Map.Entry<QName, XmlSchemaElement> entry = schema.getElements().entrySet().iterator().next();
// Get all the elements based on the parent element
XmlSchemaElement childElement = xmlSchemaCollection.getElementByQName(entry.getKey());
// Call method to get all the child elements
getChildElementNames(childElement);
// Get the elements type based on choice
List<XmlSchemaElement> childElements = xsdElements.get(new QName("food"));
System.out.println(childElements.get(0));
// Method to check for the child elements and return list
private static void getChildElementNames(XmlSchemaElement element)
// Get the type of the element
XmlSchemaType elementType = element != null ? element.getSchemaType() : null;
// Confirm if the element is of Complex type
if (elementType instanceof XmlSchemaComplexType)
// Get all particles associated with that element Type
XmlSchemaParticle allParticles = ((XmlSchemaComplexType) elementType).getParticle();
// Check particle belongs to which type
if (allParticles instanceof XmlSchemaSequence)
// System.out.println("Sequence Schema Type");
final XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) allParticles;
final List<XmlSchemaSequenceMember> items = xmlSchemaSequence.getItems();
items.forEach((item) ->
XmlSchemaElement itemElements = (XmlSchemaElement) item;
schemaElements.add(itemElements);
addChild(element.getQName(), itemElements);
// Call method recursively to get all subsequent element
getChildElementNames(itemElements);
schemaElements = new ArrayList<XmlSchemaElement>();
);
// Add child elements based on its parent
private static void addChild(QName qName, XmlSchemaElement child)
List<XmlSchemaElement> values = xsdElements.get(qName);
if (values == null)
values = new ArrayList<XmlSchemaElement>();
values.add(child);
xsdElements.put(qName, values);
【问题讨论】:
请您简化您的问题。那里的信息太多了。如有必要,减少您的 XSD 和代码,直到它们仅显示您所询问的问题。 @kimbert 感谢您的回复。为了更好地阅读,我减少了我的XSD
内容和代码。希望这可以帮助。请看一下,让我知道您是否可以针对此问题提出建议,因为我仍在寻找答案。
为什么你希望 parentSchema -> items -> [0] 包含特定元素的父元素?当然,parentSchema 代表整个模式模型,而 parentSchema->items 可能代表***声明(或其他东西)。建议您检查您的假设。
@kimbert 感谢您分析并提供您的解决方案。是的,后来我意识到了。我正在查看parentSchema
,它可能不包含该元素的直接父级。如果不包含,那么如何获取child
的父元素?有没有其他方法可以为孩子获取immediate parentElement
?
【参考方案1】:
免责声明:我不是 XSModel 方面的专家,但我确实使用过一次,很久以前。
XSModel 是 XSD 中几乎所有内容的完整记录。因此,它确实包含您正在寻找的信息。认识到 XSModel 是为了验证 XML 文档而创建的,这可能会有所帮助——它从来没有打算成为 XSD 模型的通用内存表示。如果这就是您所需要的,那么您可能会使用Eclipse XSD model 做得更好。无论哪种方式,加载和操作 XSD 模型都是一项少数运动,您不应该期望 API 会被完美记录。
您能否帮助我在 Apache XMLSchema 核心库中找到子元素的直接父元素。
当您谈论“子元素”时,我认为您的意思是 local element declaration
或 element reference
。通常,它们都可以有多个父元素声明,因为它们可以在全局复杂类型中声明。如果该全局复杂类型定义被多个元素声明使用,那么您的“子元素”将具有多个可能的父元素。
【讨论】:
感谢您的回复和信息。我仍在寻找如何找到我的子元素的直接父级。您能否帮助我在Apache XMLSchema core
库中找到子元素的直接父级。我知道它包含我所需的信息,但我不确定如何以及在哪里找到它。因此,我在这里请求希望得到一些回应。
答案已更新。您已经针对 XSModel 提出了三个不同的问题,但我仍然不清楚您要完成什么。如果您需要进一步的帮助,请确保您的下一个问题解释了您的程序的用途 - 如果我们了解您的技术目标,我们可能会提供更有用的答案。【参考方案2】:
在 Java 中的 Apache XMLSchema Core
库上工作了一段时间后,我的观察结果如下。
没有办法直接使用库获取直接父元素,您可以从 XmlSchemaElement 中获取与当前元素及其子元素相关的信息。
【讨论】:
以上是关于Apache XMLSchema 核心 XSD/XML 解析器将根元素显示为所有子元素的父元素,而不是其直接父元素的主要内容,如果未能解决你的问题,请参考以下文章
Axis2错误 - java.lang.NoClassDefFoundError:org / apache / ws / commons / schema / XmlSchema