문제

자동화 된 테스트 앱에서 작업 중이며 현재 동일하지만 두 개의 XML 파일 사이의 값을 비교하는 함수를 작성하는 과정에 있습니다. 다음은 처리하려는 XML 샘플입니다.

<?xml version="1.0" encoding="utf-8"?>
<report xmlns="http://www.**.com/**">
  <subreport name="RBDReport">
    <record rowNumber="1">
      <field name="Time">
        <value>0</value>
      </field>
      <field name="Reliability">
        <value>1.000000</value>
      </field>
      <field name="Unreliability">
        <value>0.000000</value>
      </field>
      <field name="Availability">
        <value> </value>
      </field>
      <field name="Unavailability">
        <value> </value>
      </field>
      <field name="Failure Rate">
        <value>N/A</value>
      </field>
      <field name="Number of Failures">
        <value> </value>
      </field>
      <field name="Total Downtime">
        <value> </value>
      </field>
    </record>

(여러 가지가있을 수 있습니다 <subreport> 요소와 그 안에 다중 <record> 집단.)

내가 원하는 것은 추출하는 것입니다 <value> 두 문서의 태그를 한 다음 값을 비교합니다. 그 부분은 내가하는 방법을 알고 있습니다. 문제는 추출 자체입니다.

C ++에 갇혀 있기 때문에 MSXML을 사용하고 있으며 데이터 형식을 변경하기로 결정한 경우 앱이 실제 XML 조작을 추상화 할 수 있도록 래퍼를 작성했습니다.

해당 래퍼 인 CSIMPLEXMLPARSER는 XML 문서를로드하고 XML 문서의 문서 요소로 "Top Record"를 설정합니다. (CRECORD는 CXMLRECORD의 하위 클래스 중 하나를 가진 추상 클래스이며, 하위 기록에 특이 또는 그룹별로 어린이 기록에 액세스 할 수 있으며 레코드의 "값"에 액세스 할 수 있습니다 (CXMLRECORD의 경우 자식 요소 또는 속성에 대한 값 .) cxmlrecord에는 msxml :: msxmldomnodeptr가 포함되어 있고 csimplexmlparser의 인스턴스에 대한 포인터가 포함되어 있습니다.) 래퍼는 또한 어린이를 반환하기위한 유틸리티 함수가 포함되어 있으며, 이는 Cxmlrecord가 자식 기록을 반환하는 데 사용합니다.

내 코드에서 나는 다음을 수행한다 (모든 것을 반환하려고 <subreport> 작동하는지 확인하기 위해 노드) :

CSimpleXMLParser parserReportData;
parserReportData.OpenXMLDocument(strPathToXML);
bool bGetChildrenSuccess = parserReportData.GetFirstRecord()->GetChildRecords(listpChildren, _T("subreport"));

이것은 항상 거짓을 반환합니다. cxmlrecord :: getChildRecords () 구현의 고기는 기본적으로

MSXML2::IXMLDOMNodeListPtr pListChildren = m_pParser->SelectNodes(strPath, m_pXMLNode);

if (pListChildren->Getlength() == 0)
{
    return false;
}

for (long l = 0; l < pListChildren->Getlength(); ++l)
{
    listRecords.push_back(new CXMLRecord(pListChildren->Getitem(l), m_pParser));
}

return true;

그리고 csimplexmlparser :: selectNodes ()는 다음과 같습니다.

MSXML2::IXMLDOMNodeListPtr CSimpleXMLParser::SelectNodes(LPCTSTR strXPathFilter, MSXML2::IXMLDOMNodePtr pXMLNode)
{
    return pXMLNode->selectNodes(_bstr_t(strXPathFilter));
}

실행되면 최상위 레코드가 확실히 <report> 요소가 올바르게. 자식 노드를 얻는 것과 같은 모든 종류의 일을 할 수 있습니다 (래퍼 이름이 아닌 MSXML 인터페이스를 통해) 또는 이름 등. 내 래퍼를 알고 있습니다. ~할 수 있다 XML 구성 파일을 구문 분석하기 위해 앱의 다른 곳에서 사용하고 완벽하게 작동하기 때문에 작동합니다.

XPath 쿼리 표현식으로 잘못한 일을하고 있다고 생각했지만, 내가 생각할 수있는 모든 순열은 기쁨을 줄 수 없습니다. 그만큼 MSXML::IXMLDOMNodeListPtr 반환 IXMLDOMNodePtr::SelectNodes() 이 XML 파일을 처리하려고 할 때 항상 길이 0입니다.

이것은 나를 미치게합니다.

도움이 되었습니까?

해결책

.NET의 XMLDocument 객체 로이 작업을 수행하는 데 익숙하지만 효과가 동일하다고 생각합니다.

XML 문서에 이름이없는 네임 스페이스가 포함 된 경우 XPath 쿼리도 사용해야합니다. 따라서 코드에 이름을 제공 할 수있는 XMLDoument에 네임 스페이스를 추가해야하며 XPATH 쿼리에 접두사를 포함시켜야합니다 (접두사가 XML 문서와 XML 문서와 다르지는 않습니다. XPath, 네임 스페이스가 정렬하는 한)

따라서 XPath와 같은 것을 사용하는 동안 /report/subreport/record/field/value, 실제로 문서의 네임 스페이스를 먼저 설정해야합니다.

  pXMLDoc->setProperty(_bstr_t("SelectionNamespaces"),
                       _bstr_t("xmlns:r="http://www.**.com/**"));

그리고 selectNodes() 사용 /r:report/r:subreport/r:record/r:field/r:value

다른 팁

노드를 선택할 때 네임 스페이스에 대한 언급이 없습니다. 나는 이것이 근본적인 문제라고 기대한다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top